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 2008/04/15 09:54:24 UTC

svn commit: r648156 - in /poi/trunk/src/scratchpad: examples/src/org/apache/poi/hslf/examples/ src/org/apache/poi/hslf/model/ testcases/org/apache/poi/hslf/data/ testcases/org/apache/poi/hslf/model/ testcases/org/apache/poi/hslf/usermodel/

Author: yegor
Date: Tue Apr 15 00:54:20 2008
New Revision: 648156

URL: http://svn.apache.org/viewvc?rev=648156&view=rev
Log:
TextShape is a common superclass of all shapes that can hold text. The subclasses are TextBox and AutoShape.

Added:
    poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java   (with props)
    poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/data/text_shapes.ppt   (with props)
    poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java   (with props)
Modified:
    poi/trunk/src/scratchpad/examples/src/org/apache/poi/hslf/examples/ApacheconEU08.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/AutoShape.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Line.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TableCell.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java
    poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java
    poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java

Modified: poi/trunk/src/scratchpad/examples/src/org/apache/poi/hslf/examples/ApacheconEU08.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/examples/src/org/apache/poi/hslf/examples/ApacheconEU08.java?rev=648156&r1=648155&r2=648156&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/examples/src/org/apache/poi/hslf/examples/ApacheconEU08.java (original)
+++ poi/trunk/src/scratchpad/examples/src/org/apache/poi/hslf/examples/ApacheconEU08.java Tue Apr 15 00:54:20 2008
@@ -459,6 +459,7 @@
         TextBox box2 = new TextBox();
         TextRun tr2 = box2.getTextRun();
         tr2.setRunType(TextHeaderAtom.BODY_TYPE);
+        tr2.getRichTextRuns()[0].setFontSize(32);
         tr2.setText(
                 "Support for more PowerPoint functionality\r" +
                 "Rendering slides into java.awt.Graphics2D");
@@ -477,6 +478,7 @@
         TextBox box4 = new TextBox();
         TextRun tr4 = box4.getTextRun();
         tr4.setRunType(TextHeaderAtom.BODY_TYPE);
+        tr4.getRichTextRuns()[0].setFontSize(32);
         tr4.setText(
                 "Integration with Apache FOP - Formatting Objects Processor");
         box4.setAnchor(new Rectangle(36, 290, 648, 90));

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/AutoShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/AutoShape.java?rev=648156&r1=648155&r2=648156&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/AutoShape.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/AutoShape.java Tue Apr 15 00:54:20 2008
@@ -20,11 +20,15 @@
 import org.apache.poi.ddf.*;
 
 /**
- * Represents a autoshape in a PowerPoint drawing
+ * Represents an AutoShape.
+ * <p>
+ * AutoShapes are drawing objects with a particular shape that may be customized through smart resizing and adjustments.
+ * See {@link ShapeTypes}
+ * </p>
  *
  *  @author Yegor Kozlov
  */
-public class AutoShape extends SimpleShape {
+public class AutoShape extends TextShape {
 
     protected AutoShape(EscherContainerRecord escherRecord, Shape parent){
         super(escherRecord, parent);
@@ -40,23 +44,62 @@
     }
 
     protected EscherContainerRecord createSpContainer(int shapeType, boolean isChild){
-        EscherContainerRecord spcont = super.createSpContainer(isChild);
+        _escherContainer = super.createSpContainer(isChild);
 
-        EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);
-        short type = (short)((shapeType << 4) | 0x2);
-        spRecord.setOptions(type);
+        setShapeType(shapeType);
 
         //set default properties for an autoshape
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID);
+        setEscherProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x40000);
+        setEscherProperty(EscherProperties.FILL__FILLCOLOR, 0x8000004);
+        setEscherProperty(EscherProperties.FILL__FILLCOLOR, 0x8000004);
+        setEscherProperty(EscherProperties.FILL__FILLBACKCOLOR, 0x8000000);
+        setEscherProperty(EscherProperties.FILL__NOFILLHITTEST, 0x100010);
+        setEscherProperty(EscherProperties.LINESTYLE__COLOR, 0x8000001);
+        setEscherProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x80008);
+        setEscherProperty(EscherProperties.SHADOWSTYLE__COLOR, 0x8000002);
 
-        opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.FILL__FILLCOLOR, 0x8000004));
-        opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.FILL__FILLBACKCOLOR, 0x8000000));
-        opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.FILL__NOFILLHITTEST, 0x100010));
-        opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__COLOR, 0x8000001));
-        opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x80008));
-        opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.SHADOWSTYLE__COLOR, 0x8000002));
+        return _escherContainer;
+    }
+
+    protected void setDefaultTextProperties(TextRun _txtrun){
+        setVerticalAlignment(TextBox.AnchorMiddle);
+        setHorizontalAlignment(TextBox.AlignCenter);
+        setWordWrap(TextBox.WrapNone);
+    }
 
-        return spcont;
+    /**
+     * Gets adjust value which controls smart resizing of the auto-shape.
+     *
+     * <p>
+     * The adjustment values are given in shape coordinates:
+     * the origin is at the top-left, positive-x is to the right, positive-y is down.
+     * The region from (0,0) to (S,S) maps to the geometry box of the shape (S=21600 is a constant).
+     * </p>
+     *
+     * @param idx the adjust index in the [0, 9] range
+     * @return the adjustment value
+     */
+    public int getAdjustmentValue(int idx){
+        if(idx < 0 || idx > 9) throw new IllegalArgumentException("The index of an adjustment value must be in the [0, 9] range");
+
+        return getEscherProperty((short)(EscherProperties.GEOMETRY__ADJUSTVALUE + idx));
     }
 
+    /**
+     * Sets adjust value which controls smart resizing of the auto-shape.
+     *
+     * <p>
+     * The adjustment values are given in shape coordinates:
+     * the origin is at the top-left, positive-x is to the right, positive-y is down.
+     * The region from (0,0) to (S,S) maps to the geometry box of the shape (S=21600 is a constant).
+     * </p>
+     *
+     * @param idx the adjust index in the [0, 9] range
+     * @param val the adjustment value
+     */
+    public void setAdjustmentValue(int idx, int val){
+        if(idx < 0 || idx > 9) throw new IllegalArgumentException("The index of an adjustment value must be in the [0, 9] range");
+
+        setEscherProperty((short)(EscherProperties.GEOMETRY__ADJUSTVALUE + idx), val);
+    }
 }

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Line.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Line.java?rev=648156&r1=648155&r2=648156&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Line.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Line.java Tue Apr 15 00:54:20 2008
@@ -106,14 +106,14 @@
     }
 
     protected EscherContainerRecord createSpContainer(boolean isChild){
-        EscherContainerRecord spcont = super.createSpContainer(isChild);
+        _escherContainer = super.createSpContainer(isChild);
 
-        EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);
+        EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
         short type = (ShapeTypes.Line << 4) | 0x2;
         spRecord.setOptions(type);
   
         //set default properties for a line
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID);
+        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
 
         //default line properties
         setEscherProperty(opt, EscherProperties.GEOMETRY__SHAPEPATH, 4);
@@ -123,7 +123,7 @@
         setEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0xA0008);
         setEscherProperty(opt, EscherProperties.SHADOWSTYLE__COLOR, 0x8000002);
 
-        return spcont;
+        return _escherContainer;
     }
 
 }

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java?rev=648156&r1=648155&r2=648156&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java Tue Apr 15 00:54:20 2008
@@ -120,20 +120,20 @@
      * @return the create Picture object
      */
     protected EscherContainerRecord createSpContainer(int idx, boolean isChild) {
-        EscherContainerRecord spContainer = super.createSpContainer(isChild);
-        spContainer.setOptions((short)15);
+        _escherContainer = super.createSpContainer(isChild);
+        _escherContainer.setOptions((short)15);
 
-        EscherSpRecord spRecord = spContainer.getChildById(EscherSpRecord.RECORD_ID);
+        EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
         spRecord.setOptions((short)((ShapeTypes.PictureFrame << 4) | 0x2));
 
         //set default properties for a picture
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(spContainer, EscherOptRecord.RECORD_ID);
+        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
         setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 8388736);
 
         //another weird feature of powerpoint: for picture id we must add 0x4000.
         setEscherProperty(opt, (short)(EscherProperties.BLIP__BLIPTODISPLAY + 0x4000), idx);
 
-        return spContainer;
+        return _escherContainer;
     }
 
     /**

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java?rev=648156&r1=648155&r2=648156&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java Tue Apr 15 00:54:20 2008
@@ -49,15 +49,15 @@
      * @return the created <code>EscherContainerRecord</code> which holds shape data
      */
     protected EscherContainerRecord createSpContainer(boolean isChild){
-        EscherContainerRecord spcont = super.createSpContainer(isChild);
+        _escherContainer = super.createSpContainer(isChild);
 
-        EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);
+        EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
         spRecord.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HAVEMASTER);
 
         EscherClientDataRecord cldata = new EscherClientDataRecord();
         cldata.setOptions((short)15);
 
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID);
+        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
 
         //Placeholders can't be grouped
         setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 262144);
@@ -86,7 +86,7 @@
         cldata.setRemainingData(out.toByteArray());
 
         //append placeholder container before EscherTextboxRecord
-        List lst = spcont.getChildRecords();
+        List lst = _escherContainer.getChildRecords();
         for (int i = 0; i < lst.size(); i++) {
               EscherRecord rec = (EscherRecord)lst.get(i);
               if(rec.getRecordId() == EscherTextboxRecord.RECORD_ID){
@@ -94,6 +94,6 @@
               }
         }
 
-        return spcont;
+        return _escherContainer;
     }
 }

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java?rev=648156&r1=648155&r2=648156&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java Tue Apr 15 00:54:20 2008
@@ -39,12 +39,7 @@
         int type = spRecord.getOptions() >> 4;
         switch (type){
             case ShapeTypes.TextBox:
-            case ShapeTypes.Rectangle:
-                EscherTextboxRecord txtbox = (EscherTextboxRecord)Shape.getEscherChild(spContainer, EscherTextboxRecord.RECORD_ID);
-                if (txtbox == null)
-                    shape = new AutoShape(spContainer, parent);
-                else
-                    shape = new TextBox(spContainer, parent);
+                shape = new TextBox(spContainer, parent);
                 break;
             case ShapeTypes.PictureFrame:
                 shape = new Picture(spContainer, parent);
@@ -54,9 +49,13 @@
                 break;
             case ShapeTypes.NotPrimitive:
                 if ((spRecord.getFlags() & EscherSpRecord.FLAG_GROUP) != 0)
-                     shape = new ShapeGroup(spContainer, parent);
-                else
+                    //TODO: check if the shape group is a Table 
+                    shape = new ShapeGroup(spContainer, parent);
+                else {
+                    //TODO: check if the shape has GEOMETRY__VERTICES or GEOMETRY__SEGMENTINFO properties.
+                    //if it does, then return Freeform or Polygon
                     shape = new AutoShape(spContainer, parent);
+                }
                 break;
             default:
                 shape = new AutoShape(spContainer, parent);

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java?rev=648156&r1=648155&r2=648156&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java Tue Apr 15 00:54:20 2008
@@ -19,6 +19,7 @@
 import org.apache.poi.ddf.*;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.POILogger;
+import org.apache.poi.hslf.record.EscherTextboxWrapper;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -154,9 +155,10 @@
         shape.setSheet(sheet);
         shape.afterInsert(sheet);
 
-        if(shape instanceof TextBox) {
-            TextBox tbox = (TextBox)shape;
-            getSheet().getPPDrawing().addTextboxWrapper(tbox._txtbox);
+        if (shape instanceof TextShape) {
+            TextShape tbox = (TextShape) shape;
+            EscherTextboxWrapper txWrapper = tbox.getEscherTextboxWrapper();
+            if(txWrapper != null) getSheet().getPPDrawing().addTextboxWrapper(txWrapper);
         }
     }
 

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java?rev=648156&r1=648155&r2=648156&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java Tue Apr 15 00:54:20 2008
@@ -257,11 +257,12 @@
         shape.setSheet(this);
         shape.afterInsert(this);
 
-        // If it's a TextBox, we need to tell the PPDrawing, as it has to
+        // If it's a TextShape, we need to tell the PPDrawing, as it has to
         //  track TextboxWrappers specially
-        if (shape instanceof TextBox) {
-            TextBox tbox = (TextBox) shape;
-            ppdrawing.addTextboxWrapper(tbox._txtbox);
+        if (shape instanceof TextShape) {
+            TextShape tbox = (TextShape) shape;
+            EscherTextboxWrapper txWrapper = tbox.getEscherTextboxWrapper();
+            if(txWrapper != null) ppdrawing.addTextboxWrapper(txWrapper);
         }
     }
 

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java?rev=648156&r1=648155&r2=648156&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java Tue Apr 15 00:54:20 2008
@@ -48,19 +48,19 @@
      * @return the record container which holds this shape
      */
     protected EscherContainerRecord createSpContainer(boolean isChild) {
-        EscherContainerRecord spContainer = new EscherContainerRecord();
-        spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
-        spContainer.setOptions((short)15);
+        _escherContainer = new EscherContainerRecord();
+        _escherContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
+        _escherContainer.setOptions((short)15);
 
         EscherSpRecord sp = new EscherSpRecord();
         int flags = EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE;
         if (isChild) flags |= EscherSpRecord.FLAG_CHILD;
         sp.setFlags(flags);
-        spContainer.addChildRecord(sp);
+        _escherContainer.addChildRecord(sp);
 
         EscherOptRecord opt = new EscherOptRecord();
         opt.setRecordId(EscherOptRecord.RECORD_ID);
-        spContainer.addChildRecord(opt);
+        _escherContainer.addChildRecord(opt);
 
         EscherRecord anchor;
         if(isChild) anchor = new EscherChildAnchorRecord();
@@ -75,9 +75,9 @@
             LittleEndian.putInt(header, 4, 8);
             anchor.fillFields(header, 0, null);
         }
-        spContainer.addChildRecord(anchor);
+        _escherContainer.addChildRecord(anchor);
 
-        return spContainer;
+        return _escherContainer;
     }
 
     /**

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TableCell.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TableCell.java?rev=648156&r1=648155&r2=648156&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TableCell.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TableCell.java Tue Apr 15 00:54:20 2008
@@ -63,15 +63,15 @@
     }
 
     protected EscherContainerRecord createSpContainer(boolean isChild){
-        EscherContainerRecord spContainer = super.createSpContainer(isChild);
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(spContainer, EscherOptRecord.RECORD_ID);
+        _escherContainer = super.createSpContainer(isChild);
+        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
         setEscherProperty(opt, EscherProperties.TEXT__TEXTID, 0);
         setEscherProperty(opt, EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x20000);
         setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x150001);
         setEscherProperty(opt, EscherProperties.SHADOWSTYLE__SHADOWOBSURED, 0x20000);
         setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x40000);
 
-        return spContainer;
+        return _escherContainer;
     }
 
     protected void anchorBorder(int type, Line line){

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java?rev=648156&r1=648155&r2=648156&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java Tue Apr 15 00:54:20 2008
@@ -38,55 +38,7 @@
  *
  * @author Yegor Kozlov
  */
-public class TextBox extends SimpleShape {
-
-    /**
-     * How to anchor the text
-     */
-    public static final int AnchorTop = 0;
-    public static final int AnchorMiddle = 1;
-    public static final int AnchorBottom = 2;
-    public static final int AnchorTopCentered = 3;
-    public static final int AnchorMiddleCentered = 4;
-    public static final int AnchorBottomCentered = 5;
-    public static final int AnchorTopBaseline = 6;
-    public static final int AnchorBottomBaseline = 7;
-    public static final int AnchorTopCenteredBaseline = 8;
-    public static final int AnchorBottomCenteredBaseline = 9;
-
-    /**
-     * How to wrap the text
-     */
-    public static final int WrapSquare = 0;
-    public static final int WrapByPoints = 1;
-    public static final int WrapNone = 2;
-    public static final int WrapTopBottom = 3;
-    public static final int WrapThrough = 4;
-
-    /**
-     * How to align the text
-     */
-    public static final int AlignLeft = 0;
-    public static final int AlignCenter = 1;
-    public static final int AlignRight = 2;
-    public static final int AlignJustify = 3;
-
-    /**
-     * Low-level object which holds actual text and format data
-     */
-    protected TextRun _txtrun;
-
-    /**
-     * Escher container which holds text attributes such as
-     * TextHeaderAtom, TextBytesAtom ot TextCharsAtom, StyleTextPropAtom etc.
-     */
-    protected EscherTextboxWrapper _txtbox;
-    
-    /**
-     * Is the TextBox missing the text records which actually
-     *  store the text?
-     */
-    private boolean _missingTextRecords = false;
+public class TextBox extends TextShape {
 
     /**
      * Create a TextBox object and initialize it from the supplied Record container.
@@ -97,8 +49,6 @@
    protected TextBox(EscherContainerRecord escherRecord, Shape parent){
         super(escherRecord, parent);
 
-        EscherTextboxRecord textbox = (EscherTextboxRecord)Shape.getEscherChild(_escherContainer, EscherTextboxRecord.RECORD_ID);
-        _txtbox = new EscherTextboxWrapper(textbox);
     }
 
     /**
@@ -108,8 +58,7 @@
      * in a table then the parent is Table.
      */
     public TextBox(Shape parent){
-        super(null, parent);
-        _escherContainer = createSpContainer(parent instanceof ShapeGroup);
+        super(parent);
     }
 
     /**
@@ -121,376 +70,31 @@
     }
 
     /**
-     * Create a new textBox and initialize internal structures
+     * Create a new TextBox and initialize its internal structures
      *
      * @return the created <code>EscherContainerRecord</code> which holds shape data
      */
     protected EscherContainerRecord createSpContainer(boolean isChild){
-        EscherContainerRecord spcont = super.createSpContainer(isChild);
-
-        EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);
-        short type = (ShapeTypes.TextBox << 4) | 0x2;
-        spRecord.setOptions(type);
-
-        //set default properties for a textbox
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID);
-        setEscherProperty(opt, EscherProperties.TEXT__TEXTID, 0);
-
-        setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, 0x8000004);
-        setEscherProperty(opt, EscherProperties.FILL__FILLBACKCOLOR, 0x8000000);
-        setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x100000);
-        setEscherProperty(opt, EscherProperties.LINESTYLE__COLOR, 0x8000001);
-        setEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x80000);
-        setEscherProperty(opt, EscherProperties.SHADOWSTYLE__COLOR, 0x8000002);
+        _escherContainer = super.createSpContainer(isChild);
 
-        //create EscherTextboxWrapper
-        _txtbox = new EscherTextboxWrapper();
+        setShapeType(ShapeTypes.TextBox);
 
-        TextHeaderAtom tha = new TextHeaderAtom();
-        tha.setParentRecord(_txtbox); // TextHeaderAtom is parent aware
-        _txtbox.appendChildRecord(tha);
+        //set default properties for a TextBox
+        setEscherProperty(EscherProperties.FILL__FILLCOLOR, 0x8000004);
+        setEscherProperty(EscherProperties.FILL__FILLBACKCOLOR, 0x8000000);
+        setEscherProperty(EscherProperties.FILL__NOFILLHITTEST, 0x100000);
+        setEscherProperty(EscherProperties.LINESTYLE__COLOR, 0x8000001);
+        setEscherProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x80000);
+        setEscherProperty(EscherProperties.SHADOWSTYLE__COLOR, 0x8000002);
 
-        TextCharsAtom tca = new TextCharsAtom();
-        _txtbox.appendChildRecord(tca);
+        _txtrun = createTextRun();
 
-        StyleTextPropAtom sta = new StyleTextPropAtom(0);
-        _txtbox.appendChildRecord(sta);
-
-        _txtrun = new TextRun(tha,tca,sta);
-        _txtrun.setText("");
-        spcont.addChildRecord(_txtbox.getEscherRecord());
-
-        return spcont;
+        return _escherContainer;
     }
 
-    /**
-     * Returns the text contained in this text frame.
-     *
-     * @return the text string for this textbox.
-     */
-     public String getText(){
-        return _txtrun == null ? null : _txtrun.getText();
+    protected void setDefaultTextProperties(TextRun _txtrun){
+        setVerticalAlignment(TextBox.AnchorTop);
+        setEscherProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x20002);
     }
 
-    /**
-     * Sets the text contained in this text frame.
-     *
-     * @param text the text string used by this object.
-     */
-    public void setText(String text){
-        _txtrun.setText(text);
-    }
-
-    /**
-     * When a textbox is added to  a sheet we need to tell upper-level
-     * <code>PPDrawing</code> about it.
-     *
-     * @param sh the sheet we are adding to
-     */
-    protected void afterInsert(Sheet sh){
-        PPDrawing ppdrawing = sh.getPPDrawing();
-        ppdrawing.addTextboxWrapper(_txtbox);
-        // Ensure the escher layer knows about the added records 
-        try {
-            _txtbox.writeOut(null);
-        } catch (IOException e){
-            throw new HSLFException(e);
-        }
-        if(getAnchor().equals(new java.awt.Rectangle()) && !"".equals(getText())) resizeToFitText();
-    }
-
-    /**
-     * Adjust the size of the TextBox so it encompasses the text inside it.
-     */
-    public void resizeToFitText(){
-        try{
-        FontRenderContext frc = new FontRenderContext(null, true, true);
-        RichTextRun rt = _txtrun.getRichTextRuns()[0];
-        int size = rt.getFontSize();
-        int style = 0;
-        if (rt.isBold()) style |= Font.BOLD;
-        if (rt.isItalic()) style |= Font.ITALIC;
-        String fntname = rt.getFontName();
-        Font font = new Font(fntname, style, size);
-
-        TextLayout layout = new TextLayout(getText(), font, frc);
-        int width = Math.round(layout.getAdvance());
-        int height = Math.round(layout.getAscent());
-
-        Dimension txsize = new Dimension(width, height);
-        java.awt.Rectangle anchor = getAnchor();
-        anchor.setSize(txsize);
-        setAnchor(anchor);
-        } catch (Exception e){
-            e.printStackTrace();
-
-        }
-    }
-
-    /**
-     * Returns the type of vertical alignment for the text.
-     * One of the <code>Anchor*</code> constants defined in this class.
-     *
-     * @return the type of alignment
-     */
-    public int getVerticalAlignment(){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT);
-        int valign;
-        if (prop == null){
-            int type = getTextRun().getRunType();
-            switch (type){
-                case TextHeaderAtom.TITLE_TYPE:
-                case TextHeaderAtom.CENTER_TITLE_TYPE:
-                    valign = TextBox.AnchorMiddle;
-                    break;
-                default:
-                    valign = TextBox.AnchorTop;
-                    break;
-            }
-        } else {
-            valign = prop.getPropertyValue();
-        }
-        return valign;
-    }
-
-    /**
-     * Sets the type of vertical alignment for the text.
-     * One of the <code>Anchor*</code> constants defined in this class.
-     *
-     * @param align - the type of alignment
-     */
-    public void setVerticalAlignment(int align){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        setEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT, align);
-    }
-
-    public void setHorizontalAlignment(int align){
-        _txtrun.getRichTextRuns()[0].setAlignment(align);
-    }
-    public int getHorizontalAlignment(){
-        return _txtrun.getRichTextRuns()[0].getAlignment();
-    }
-
-    /**
-     * Returns the distance (in points) between the bottom of the text frame
-     * and the bottom of the inscribed rectangle of the shape that contains the text.
-     * Default value is 1/20 inch.
-     *
-     * @return the botom margin
-     */
-    public int getMarginBottom(){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM);
-        int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
-        return val/EMU_PER_POINT;
-    }
-
-    /**
-     * Sets the botom margin.
-     * @see #getMarginBottom()
-     *
-     * @param margin    the bottom margin
-     */
-    public void setMarginBottom(int margin){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        setEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM, margin*EMU_PER_POINT);
-    }
-
-    /**
-     *  Returns the distance (in EMUs) between the left edge of the text frame
-     *  and the left edge of the inscribed rectangle of the shape that contains
-     *  the text.
-     *  Default value is 1/10 inch.
-     *
-     * @return the left margin
-     */
-    public int getMarginLeft(){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM);
-        int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
-        return val/EMU_PER_POINT;
-    }
-
-    /**
-     * Sets the left margin.
-     * @see #getMarginLeft()
-     *
-     * @param margin    the left margin
-     */
-    public void setMarginLeft(int margin){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        setEscherProperty(opt, EscherProperties.TEXT__TEXTLEFT, margin*EMU_PER_POINT);
-    }
-
-    /**
-     *  Returns the distance (in EMUs) between the right edge of the
-     *  text frame and the right edge of the inscribed rectangle of the shape
-     *  that contains the text.
-     *  Default value is 1/10 inch.
-     *
-     * @return the right margin
-     */
-    public int getMarginRight(){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTRIGHT);
-        int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
-        return val/EMU_PER_POINT;
-    }
-
-    /**
-     * Sets the right margin.
-     * @see #getMarginRight()
-     *
-     * @param margin    the right margin
-     */
-    public void setMarginRight(int margin){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        setEscherProperty(opt, EscherProperties.TEXT__TEXTRIGHT, margin*EMU_PER_POINT);
-    }
-
-     /**
-     *  Returns the distance (in EMUs) between the top of the text frame
-     *  and the top of the inscribed rectangle of the shape that contains the text.
-     *  Default value is 1/20 inch.
-     *
-     * @return the top margin
-     */
-    public int getMarginTop(){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTTOP);
-        int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
-        return val/EMU_PER_POINT;
-    }
-
-   /**
-     * Sets the top margin.
-     * @see #getMarginTop()
-     *
-     * @param margin    the top margin
-     */
-    public void setMarginTop(int margin){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        setEscherProperty(opt, EscherProperties.TEXT__TEXTTOP, margin*EMU_PER_POINT);
-    }
-
-
-    /**
-     * Returns the value indicating word wrap.
-     * One of the <code>Wrap*</code> constants defined in this class.
-     *
-     * @return the value indicating word wrap
-     */
-    public int getWordWrap(){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT);
-        return prop == null ? WrapSquare : prop.getPropertyValue();
-    }
-
-    /**
-     *  Specifies how the text should be wrapped
-     *
-     * @param wrap  the value indicating how the text should be wrapped
-     */
-    public void setWordWrap(int wrap){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        setEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT, wrap);
-    }
-
-    /**
-     * @return id for the text.
-     */
-    public int getTextId(){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTID);
-        return prop == null ? 0 : prop.getPropertyValue();
-    }
-
-    /**
-     * Sets text ID
-     *
-     * @param id of the text
-     */
-    public void setTextId(int id){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        setEscherProperty(opt, EscherProperties.TEXT__TEXTID, id);
-    }
-
-    /**
-     * The color used to fill this shape.
-     *
-     * @param color the background color
-     */
-    public void setBackgroundColor(Color color){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB();
-        setEscherProperty(opt, EscherProperties.FILL__FILLBACKCOLOR, rgb);
-    }
-
-    /**
-      * @return the TextRun object for this text box
-      */
-     public TextRun getTextRun(){
-         return _txtrun;
-     }
-
-     public void setSheet(Sheet sheet){
-        _sheet = sheet;
-
-        // Initialize _txtrun object.
-        // (We can't do it in the constructor because the sheet
-        //  is not assigned then, it's only built once we have
-        //  all the records)
-        if(_txtrun == null) initTextRun();
-        if(_txtrun == null) {
-        	// No text records found, skip
-        	_missingTextRecords = true;
-        	return;
-        } else {
-        	_missingTextRecords = false;
-        }
-        
-        // Supply the sheet to our child RichTextRuns
-        _txtrun.setSheet(sheet);
-        RichTextRun[] rt = _txtrun.getRichTextRuns();
-        for (int i = 0; i < rt.length; i++) {
-            rt[i].supplySlideShow(_sheet.getSlideShow());
-        }
-    }
-
-    private void initTextRun(){
-        OutlineTextRefAtom ota = null;
-        
-        // Find the interesting child records 
-        Record[] child = _txtbox.getChildRecords();
-        for (int i = 0; i < child.length; i++) {
-            if (child[i] instanceof OutlineTextRefAtom) {
-                ota = (OutlineTextRefAtom)child[i];
-                break;
-            }
-        }
-
-        Sheet sheet = getSheet();
-        TextRun[] runs = sheet.getTextRuns();
-        if (ota != null) {
-            int idx = ota.getTextIndex();
-            for (int i = 0; i < runs.length; i++) {
-                if(runs[i].getIndex() == idx){
-                    _txtrun = runs[i];
-                }
-            }
-            if(_txtrun == null) {
-                logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx);
-            }
-        } else {
-            int shapeId = _escherContainer.getChildById(EscherSpRecord.RECORD_ID).getShapeId();
-            if(runs != null) for (int i = 0; i < runs.length; i++) {
-                if(runs[i].getShapeId() == shapeId){
-                    _txtrun = runs[i];
-                    break;
-                }
-            }
-        }
-
-    }
 }

Added: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java?rev=648156&view=auto
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java (added)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java Tue Apr 15 00:54:20 2008
@@ -0,0 +1,516 @@
+
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hslf.model;
+
+import org.apache.poi.ddf.*;
+import org.apache.poi.hslf.record.*;
+import org.apache.poi.hslf.usermodel.RichTextRun;
+import org.apache.poi.hslf.exceptions.HSLFException;
+import org.apache.poi.util.POILogger;
+
+import java.awt.*;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.AffineTransform;
+import java.awt.font.FontRenderContext;
+import java.awt.font.TextLayout;
+import java.io.IOException;
+
+/**
+ * A common superclass of all shapes that can hold text.
+ *
+ * @author Yegor Kozlov
+ */
+public abstract class TextShape extends SimpleShape {
+
+    /**
+     * How to anchor the text
+     */
+    public static final int AnchorTop = 0;
+    public static final int AnchorMiddle = 1;
+    public static final int AnchorBottom = 2;
+    public static final int AnchorTopCentered = 3;
+    public static final int AnchorMiddleCentered = 4;
+    public static final int AnchorBottomCentered = 5;
+    public static final int AnchorTopBaseline = 6;
+    public static final int AnchorBottomBaseline = 7;
+    public static final int AnchorTopCenteredBaseline = 8;
+    public static final int AnchorBottomCenteredBaseline = 9;
+
+    /**
+     * How to wrap the text
+     */
+    public static final int WrapSquare = 0;
+    public static final int WrapByPoints = 1;
+    public static final int WrapNone = 2;
+    public static final int WrapTopBottom = 3;
+    public static final int WrapThrough = 4;
+
+    /**
+     * How to align the text
+     */
+    public static final int AlignLeft = 0;
+    public static final int AlignCenter = 1;
+    public static final int AlignRight = 2;
+    public static final int AlignJustify = 3;
+
+    /**
+     * TextRun object which holds actual text and format data
+     */
+    protected TextRun _txtrun;
+
+    /**
+     * Escher container which holds text attributes such as
+     * TextHeaderAtom, TextBytesAtom ot TextCharsAtom, StyleTextPropAtom etc.
+     */
+    protected EscherTextboxWrapper _txtbox;
+
+    /**
+     * Used to calculate text bounds
+     */
+    protected static final FontRenderContext _frc = new FontRenderContext(null, true, true);
+
+    /**
+     * Create a TextBox object and initialize it from the supplied Record container.
+     * 
+     * @param escherRecord       <code>EscherSpContainer</code> container which holds information about this shape
+     * @param parent    the parent of the shape
+     */
+   protected TextShape(EscherContainerRecord escherRecord, Shape parent){
+        super(escherRecord, parent);
+
+    }
+
+    /**
+     * Create a new TextBox. This constructor is used when a new shape is created.
+     *
+     * @param parent    the parent of this Shape. For example, if this text box is a cell
+     * in a table then the parent is Table.
+     */
+    public TextShape(Shape parent){
+        super(null, parent);
+        _escherContainer = createSpContainer(parent instanceof ShapeGroup);
+    }
+
+    /**
+     * Create a new TextBox. This constructor is used when a new shape is created.
+     *
+     */
+    public TextShape(){
+        this(null);
+    }
+
+    public TextRun createTextRun(){
+        _txtbox = getEscherTextboxWrapper();
+        if(_txtbox == null) _txtbox = new EscherTextboxWrapper();
+
+        _txtrun = getTextRun();
+        if(_txtrun == null){
+            TextHeaderAtom tha = new TextHeaderAtom();
+            tha.setParentRecord(_txtbox);
+            _txtbox.appendChildRecord(tha);
+
+            TextCharsAtom tca = new TextCharsAtom();
+            _txtbox.appendChildRecord(tca);
+
+            StyleTextPropAtom sta = new StyleTextPropAtom(0);
+            _txtbox.appendChildRecord(sta);
+
+            _txtrun = new TextRun(tha,tca,sta);
+            _txtrun.setText("");
+
+            _escherContainer.addChildRecord(_txtbox.getEscherRecord());
+
+            setDefaultTextProperties(_txtrun);
+        }
+
+        return _txtrun;
+    }
+
+    /**
+     * Set default properties for the  TextRun.
+     * Depending on the text and shape type the defaults are different:
+     *   TextBox: align=left, valign=top
+     *   AutoShape: align=center, valign=middle
+     *
+     */
+    protected void setDefaultTextProperties(TextRun _txtrun){
+
+    }
+
+    /**
+     * Returns the text contained in this text frame.
+     *
+     * @return the text string for this textbox.
+     */
+     public String getText(){
+        TextRun tx = getTextRun();
+        return tx == null ? null : tx.getText();
+    }
+
+    /**
+     * Sets the text contained in this text frame.
+     *
+     * @param text the text string used by this object.
+     */
+    public void setText(String text){
+        TextRun tx = getTextRun();
+        if(tx == null){
+            tx = createTextRun();
+        }
+        tx.setText(text);
+        setTextId(text.hashCode());
+    }
+
+    /**
+     * When a textbox is added to  a sheet we need to tell upper-level
+     * <code>PPDrawing</code> about it.
+     *
+     * @param sh the sheet we are adding to
+     */
+    protected void afterInsert(Sheet sh){
+        EscherTextboxWrapper _txtbox = getEscherTextboxWrapper();
+        if(_txtbox != null){
+            PPDrawing ppdrawing = sh.getPPDrawing();
+            ppdrawing.addTextboxWrapper(_txtbox);
+            // Ensure the escher layer knows about the added records
+            try {
+                _txtbox.writeOut(null);
+            } catch (IOException e){
+                throw new HSLFException(e);
+            }
+            if(getAnchor().equals(new Rectangle()) && !"".equals(getText())) resizeToFitText();
+        }
+    }
+
+    protected EscherTextboxWrapper getEscherTextboxWrapper(){
+        if(_txtbox == null){
+            EscherTextboxRecord textRecord = (EscherTextboxRecord)Shape.getEscherChild(_escherContainer, EscherTextboxRecord.RECORD_ID);
+            if(textRecord != null) _txtbox = new EscherTextboxWrapper(textRecord);
+        }
+        return _txtbox;
+    }
+    /**
+     * Adjust the size of the TextShape so it encompasses the text inside it.
+     *
+     * @return a <code>Rectangle2D</code> that is the bounds of this <code>TextShape</code>.
+     */
+    public Rectangle2D resizeToFitText(){
+        String txt = getText();
+        if(txt == null || txt.length() == 0) return new Rectangle2D.Float();
+
+        RichTextRun rt = getTextRun().getRichTextRuns()[0];
+        int size = rt.getFontSize();
+        int style = 0;
+        if (rt.isBold()) style |= Font.BOLD;
+        if (rt.isItalic()) style |= Font.ITALIC;
+        String fntname = rt.getFontName();
+        Font font = new Font(fntname, style, size);
+
+        float width = 0, height = 0;
+        String[] lines = txt.split("\r");
+        for (int i = 0; i < lines.length; i++) {
+            if(lines[i].length() == 0) continue;
+
+            TextLayout layout = new TextLayout(lines[i], font, _frc);
+
+            width = Math.max(width, layout.getAdvance());
+
+            /**
+             * Even if top and bottom margins are set to 0 PowerPoint
+             * always sets extra space between the text and its bounding box.
+             *
+             * The approximation height = ascent*2 works good enough in most cases
+             */
+            height = Math.max(height, 2*layout.getAscent());
+        }
+
+        width += getMarginLeft() + getMarginRight();
+        height += getMarginTop() + getMarginBottom();
+
+        Rectangle2D anchor = getAnchor2D();
+        anchor.setRect(anchor.getX(), anchor.getY(), width, height);
+        setAnchor(anchor);
+
+        return anchor;
+    }
+
+    /**
+     * Returns the type of vertical alignment for the text.
+     * One of the <code>Anchor*</code> constants defined in this class.
+     *
+     * @return the type of alignment
+     */
+    public int getVerticalAlignment(){
+        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT);
+        int valign;
+        if (prop == null){
+            int type = getTextRun().getRunType();
+            switch (type){
+                case TextHeaderAtom.TITLE_TYPE:
+                case TextHeaderAtom.CENTER_TITLE_TYPE:
+                    valign = TextShape.AnchorMiddle;
+                    break;
+                default:
+                    valign = TextShape.AnchorTop;
+                    break;
+            }
+        } else {
+            valign = prop.getPropertyValue();
+        }
+        return valign;
+    }
+
+    /**
+     * Sets the type of vertical alignment for the text.
+     * One of the <code>Anchor*</code> constants defined in this class.
+     *
+     * @param align - the type of alignment
+     */
+    public void setVerticalAlignment(int align){
+        setEscherProperty(EscherProperties.TEXT__ANCHORTEXT, align);
+    }
+
+    /**
+     * Sets the type of horizontal alignment for the text.
+     * One of the <code>Align*</code> constants defined in this class.
+     *
+     * @param align - the type of horizontal alignment
+     */
+    public void setHorizontalAlignment(int align){
+        TextRun tx = getTextRun();
+        if(tx != null) tx.getRichTextRuns()[0].setAlignment(align);
+    }
+
+    /**
+     * Gets the type of horizontal alignment for the text.
+     * One of the <code>Align*</code> constants defined in this class.
+     *
+     * @return align - the type of horizontal alignment
+     */
+    public int getHorizontalAlignment(){
+        TextRun tx = getTextRun();
+        return tx == null ? -1 : tx.getRichTextRuns()[0].getAlignment();
+    }
+
+    /**
+     * Returns the distance (in points) between the bottom of the text frame
+     * and the bottom of the inscribed rectangle of the shape that contains the text.
+     * Default value is 1/20 inch.
+     *
+     * @return the botom margin
+     */
+    public float getMarginBottom(){
+        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM);
+        int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
+        return (float)val/EMU_PER_POINT;
+    }
+
+    /**
+     * Sets the botom margin.
+     * @see #getMarginBottom()
+     *
+     * @param margin    the bottom margin
+     */
+    public void setMarginBottom(float margin){
+        setEscherProperty(EscherProperties.TEXT__TEXTBOTTOM, (int)(margin*EMU_PER_POINT));
+    }
+
+    /**
+     *  Returns the distance (in points) between the left edge of the text frame
+     *  and the left edge of the inscribed rectangle of the shape that contains
+     *  the text.
+     *  Default value is 1/10 inch.
+     *
+     * @return the left margin
+     */
+    public float getMarginLeft(){
+        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM);
+        int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
+        return (float)val/EMU_PER_POINT;
+    }
+
+    /**
+     * Sets the left margin.
+     * @see #getMarginLeft()
+     *
+     * @param margin    the left margin
+     */
+    public void setMarginLeft(float margin){
+        setEscherProperty(EscherProperties.TEXT__TEXTLEFT, (int)(margin*EMU_PER_POINT));
+    }
+
+    /**
+     *  Returns the distance (in points) between the right edge of the
+     *  text frame and the right edge of the inscribed rectangle of the shape
+     *  that contains the text.
+     *  Default value is 1/10 inch.
+     *
+     * @return the right margin
+     */
+    public float getMarginRight(){
+        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTRIGHT);
+        int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
+        return (float)val/EMU_PER_POINT;
+    }
+
+    /**
+     * Sets the right margin.
+     * @see #getMarginRight()
+     *
+     * @param margin    the right margin
+     */
+    public void setMarginRight(float margin){
+        setEscherProperty(EscherProperties.TEXT__TEXTRIGHT, (int)(margin*EMU_PER_POINT));
+    }
+
+     /**
+     *  Returns the distance (in points) between the top of the text frame
+     *  and the top of the inscribed rectangle of the shape that contains the text.
+     *  Default value is 1/20 inch.
+     *
+     * @return the top margin
+     */
+    public float getMarginTop(){
+        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTTOP);
+        int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
+        return (float)val/EMU_PER_POINT;
+    }
+
+   /**
+     * Sets the top margin.
+     * @see #getMarginTop()
+     *
+     * @param margin    the top margin
+     */
+    public void setMarginTop(float margin){
+        setEscherProperty(EscherProperties.TEXT__TEXTTOP, (int)(margin*EMU_PER_POINT));
+    }
+
+
+    /**
+     * Returns the value indicating word wrap.
+     *
+     * @return the value indicating word wrap.
+     *  Must be one of the <code>Wrap*</code> constants defined in this class.
+     */
+    public int getWordWrap(){
+        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT);
+        return prop == null ? WrapSquare : prop.getPropertyValue();
+    }
+
+    /**
+     *  Specifies how the text should be wrapped
+     *
+     * @param wrap  the value indicating how the text should be wrapped.
+     *  Must be one of the <code>Wrap*</code> constants defined in this class.
+     */
+    public void setWordWrap(int wrap){
+        setEscherProperty(EscherProperties.TEXT__WRAPTEXT, wrap);
+    }
+
+    /**
+     * @return id for the text.
+     */
+    public int getTextId(){
+        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTID);
+        return prop == null ? 0 : prop.getPropertyValue();
+    }
+
+    /**
+     * Sets text ID
+     *
+     * @param id of the text
+     */
+    public void setTextId(int id){
+        setEscherProperty(EscherProperties.TEXT__TEXTID, id);
+    }
+
+    /**
+      * @return the TextRun object for this text box
+      */
+     public TextRun getTextRun(){
+         if(_txtrun == null) initTextRun();
+         return _txtrun;
+     }
+
+    public void setSheet(Sheet sheet) {
+        _sheet = sheet;
+
+        // Initialize _txtrun object.
+        // (We can't do it in the constructor because the sheet
+        //  is not assigned then, it's only built once we have
+        //  all the records)
+        TextRun tx = getTextRun();
+        if (tx != null) {
+            // Supply the sheet to our child RichTextRuns
+            tx.setSheet(_sheet);
+            RichTextRun[] rt = tx.getRichTextRuns();
+            for (int i = 0; i < rt.length; i++) {
+                rt[i].supplySlideShow(_sheet.getSlideShow());
+            }
+        }
+
+    }
+
+    protected void initTextRun(){
+        EscherTextboxWrapper txtbox = getEscherTextboxWrapper();
+        Sheet sheet = getSheet();
+
+        if(sheet == null || txtbox == null) return;
+
+        OutlineTextRefAtom ota = null;
+
+        Record[] child = txtbox.getChildRecords();
+        for (int i = 0; i < child.length; i++) {
+            if (child[i] instanceof OutlineTextRefAtom) {
+                ota = (OutlineTextRefAtom)child[i];
+                break;
+            }
+        }
+
+        TextRun[] runs = _sheet.getTextRuns();
+        if (ota != null) {
+            int idx = ota.getTextIndex();
+            for (int i = 0; i < runs.length; i++) {
+                if(runs[i].getIndex() == idx){
+                    _txtrun = runs[i];
+                    break;
+                }
+            }
+            if(_txtrun == null) {
+                logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx);
+            }
+        } else {
+            int shapeId = _escherContainer.getChildById(EscherSpRecord.RECORD_ID).getShapeId();
+            if(runs != null) for (int i = 0; i < runs.length; i++) {
+                if(runs[i].getShapeId() == shapeId){
+                    _txtrun = runs[i];
+                    break;
+                }
+            }
+        }
+    }
+}

Propchange: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java
------------------------------------------------------------------------------
    svn:executable = *

Added: poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/data/text_shapes.ppt
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/data/text_shapes.ppt?rev=648156&view=auto
==============================================================================
Binary file - no diff available.

Propchange: poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/data/text_shapes.ppt
------------------------------------------------------------------------------
    svn:executable = *

Propchange: poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/data/text_shapes.ppt
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java?rev=648156&r1=648155&r2=648156&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java (original)
+++ poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java Tue Apr 15 00:54:20 2008
@@ -218,8 +218,8 @@
             ArrayList lst2 = new ArrayList();
             Shape[] sh = sl[k].getShapes();
             for (int i = 0; i < sh.length; i++) {
-                if (sh[i] instanceof TextBox){
-                    TextBox tbox = (TextBox)sh[i];
+                if (sh[i] instanceof TextShape){
+                    TextShape tbox = (TextShape)sh[i];
                     lst2.add(tbox.getText());
                 }
             }

Added: poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java?rev=648156&view=auto
==============================================================================
--- poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java (added)
+++ poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java Tue Apr 15 00:54:20 2008
@@ -0,0 +1,160 @@
+
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+
+package org.apache.poi.hslf.model;
+
+import junit.framework.TestCase;
+
+import java.io.*;
+import java.util.ArrayList;
+
+import org.apache.poi.hslf.usermodel.SlideShow;
+import org.apache.poi.hslf.record.TextHeaderAtom;
+
+/**
+ * Verify behavior of <code>TextShape</code> and its sub-classes
+ * 
+ * @author Yegor Kozlov
+ */
+public class TestTextShape extends TestCase {
+    protected String cwd = System.getProperty("HSLF.testdata.path");
+
+    public void testCreateAutoShape(){
+        TextShape shape = new AutoShape(ShapeTypes.Trapezoid);
+        assertNull(shape.getTextRun());
+        assertNull(shape.getText());
+        assertNull(shape.getEscherTextboxWrapper());
+
+        TextRun run = shape.createTextRun();
+        assertNotNull(run);
+        assertNotNull(shape.getTextRun());
+        assertNotNull(shape.getEscherTextboxWrapper());
+        assertEquals("", shape.getText());
+        assertSame(run, shape.createTextRun());
+
+    }
+
+    public void testCreateTextBox(){
+        TextShape shape = new TextBox();
+        TextRun run = shape.getTextRun();
+        assertNotNull(run);
+        assertNotNull(shape.getText());
+        assertNotNull(shape.getEscherTextboxWrapper());
+
+        assertSame(run, shape.createTextRun());
+        assertNotNull(shape.getTextRun());
+        assertNotNull(shape.getEscherTextboxWrapper());
+        assertEquals("", shape.getText());
+
+    }
+
+    /**
+     * Verify we can get text from TextShape in the following cases:
+     *  - placeholders
+     *  - normal TextBox object
+     *  - text in auto-shapes
+     */
+    public void testRead() throws IOException {
+        FileInputStream is = new FileInputStream(new File(cwd, "text_shapes.ppt"));
+        SlideShow ppt = new SlideShow(is);
+        is.close();
+
+        ArrayList lst1 = new ArrayList();
+        Slide slide = ppt.getSlides()[0];
+        Shape[] shape = slide.getShapes();
+        for (int i = 0; i < shape.length; i++) {
+            assertTrue("Expected TextShape but found " + shape[i].getClass().getName(), shape[i] instanceof TextShape);
+            TextShape tx = (TextShape)shape[i];
+            TextRun run = tx.getTextRun();
+            assertNotNull(run);
+            int runType = run.getRunType();
+
+            int type = shape[i].getShapeType();
+            switch (type){
+                case ShapeTypes.TextBox:
+                    assertEquals("Text in a TextBox", run.getText());
+                    break;
+                case ShapeTypes.Rectangle:
+                    if(runType == TextHeaderAtom.OTHER_TYPE)
+                        assertEquals("Rectangle", run.getText());
+                    else if(runType == TextHeaderAtom.TITLE_TYPE)
+                        assertEquals("Title Placeholder", run.getText());
+                    break;
+                case ShapeTypes.Octagon:
+                    assertEquals("Octagon", run.getText());
+                    break;
+                case ShapeTypes.Ellipse:
+                    assertEquals("Ellipse", run.getText());
+                    break;
+                case ShapeTypes.RoundRectangle:
+                    assertEquals("RoundRectangle", run.getText());
+                    break;
+                default:
+                    fail("Unexpected shape: " + shape[i].getShapeName());
+
+            }
+            lst1.add(run.getText());
+        }
+
+        ArrayList lst2 = new ArrayList();
+        TextRun[] run = slide.getTextRuns();
+        for (int i = 0; i < run.length; i++) {
+            lst2.add(run[i].getText());
+        }
+
+        assertTrue(lst1.containsAll(lst2));
+    }
+
+    public void testReadWrite() throws IOException {
+        SlideShow ppt = new SlideShow();
+        Slide slide =  ppt.createSlide();
+
+        TextShape shape1 = new TextBox();
+        TextRun run1 = shape1.createTextRun();
+        run1.setText("Hello, World!");
+        slide.addShape(shape1);
+
+        shape1.moveTo(100, 100);
+
+        TextShape shape2 = new AutoShape(ShapeTypes.Arrow);
+        TextRun run2 = shape2.createTextRun();
+        run2.setText("Testing TextShape");
+        slide.addShape(shape2);
+        shape2.moveTo(300, 300);
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        ppt.write(out);
+        out.close();
+
+        ppt = new SlideShow(new ByteArrayInputStream(out.toByteArray()));
+        slide = ppt.getSlides()[0];
+        Shape[] shape = slide.getShapes();
+
+        assertTrue(shape[0] instanceof TextShape);
+        shape1 = (TextShape)shape[0];
+        assertEquals(ShapeTypes.TextBox, shape1.getShapeType());
+        assertEquals("Hello, World!", shape1.getTextRun().getText());
+
+        assertTrue(shape[1] instanceof TextShape);
+        shape1 = (TextShape)shape[1];
+        assertEquals(ShapeTypes.Arrow, shape1.getShapeType());
+        assertEquals("Testing TextShape", shape1.getTextRun().getText());
+    }
+
+}

Propchange: poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java
------------------------------------------------------------------------------
    svn:executable = *

Modified: poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java?rev=648156&r1=648155&r2=648156&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java (original)
+++ poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java Tue Apr 15 00:54:20 2008
@@ -316,8 +316,8 @@
         ArrayList lst = new ArrayList();
         Shape[] shape = slide.getShapes();
         for (int i = 0; i < shape.length; i++) {
-            if( shape[i] instanceof TextBox){
-                TextRun textRun = ((TextBox)shape[i]).getTextRun();
+            if( shape[i] instanceof TextShape){
+                TextRun textRun = ((TextShape)shape[i]).getTextRun();
                 if(textRun != null) lst.add(textRun);
             }
 



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