You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2015/10/29 02:05:28 UTC

svn commit: r1711171 [4/5] - in /poi: site/src/documentation/content/xdocs/ trunk/src/examples/src/org/apache/poi/hslf/examples/ trunk/src/examples/src/org/apache/poi/xslf/usermodel/ trunk/src/java/org/apache/poi/sl/draw/ trunk/src/java/org/apache/poi/...

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java?rev=1711171&r1=1711170&r2=1711171&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java Thu Oct 29 01:05:27 2015
@@ -116,19 +116,11 @@ public abstract class HSLFShape implemen
         return getShapeType().nativeName;
     }
 
-    /**
-     * @return type of the shape.
-     * @see org.apache.poi.hslf.record.RecordTypes
-     */
     public ShapeType getShapeType(){
         EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
         return ShapeType.forId(spRecord.getShapeType(), false);
     }
 
-    /**
-     * @param type type of the shape.
-     * @see org.apache.poi.hslf.record.RecordTypes
-     */
     public void setShapeType(ShapeType type){
         EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
         spRecord.setShapeType( (short) type.nativeId );
@@ -209,7 +201,9 @@ public abstract class HSLFShape implemen
      * @param x the x coordinate of the top left corner of the shape
      * @param y the y coordinate of the top left corner of the shape
      */
-    public void moveTo(float x, float y){
+    public final void moveTo(float x, float y) {
+        // This convenience method should be implemented via setAnchor in subclasses
+        // see HSLFGroupShape.setAnchor() for a reference
         Rectangle anchor = getAnchor();
         anchor.setRect(x, y, anchor.getWidth(), anchor.getHeight());
         setAnchor(anchor);

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShapeFactory.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShapeFactory.java?rev=1711171&r1=1711170&r2=1711171&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShapeFactory.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShapeFactory.java Thu Oct 29 01:05:27 2015
@@ -56,7 +56,7 @@ public final class HSLFShapeFactory {
             EscherPropertyFactory f = new EscherPropertyFactory();
             List<EscherProperty> props = f.createProperties( opt.serialize(), 8, opt.getInstance() );
             for (EscherProperty ep : props) {
-                if (ep.getPropertyNumber() == 0x39F
+                if (ep.getPropertyNumber() == EscherProperties.GROUPSHAPE__TABLEPROPERTIES
                     && ep instanceof EscherSimpleProperty
                     && ((EscherSimpleProperty)ep).getPropertyValue() == 1) {
                     isTable = true;
@@ -65,9 +65,13 @@ public final class HSLFShapeFactory {
             }
         }
         
-        HSLFGroupShape group = (isTable)
-            ? new HSLFTable(spContainer, parent)
-            : new HSLFGroupShape(spContainer, parent);
+        HSLFGroupShape group;
+        if (isTable) {
+            group = new HSLFTable(spContainer, parent);
+            
+        } else {
+            group = new HSLFGroupShape(spContainer, parent);
+        }
         
         return group;
      }
@@ -82,65 +86,73 @@ public final class HSLFShapeFactory {
                 shape = new HSLFTextBox(spContainer, parent);
                 break;
             case HOST_CONTROL:
-            case FRAME: {
-                InteractiveInfo info = getClientDataRecord(spContainer, RecordTypes.InteractiveInfo.typeID);
-                OEShapeAtom oes = getClientDataRecord(spContainer, RecordTypes.OEShapeAtom.typeID);
-                if(info != null && info.getInteractiveInfoAtom() != null){
-                    switch(info.getInteractiveInfoAtom().getAction()){
-                        case InteractiveInfoAtom.ACTION_OLE:
-                            shape = new OLEShape(spContainer, parent);
-                            break;
-                        case InteractiveInfoAtom.ACTION_MEDIA:
-                            shape = new MovieShape(spContainer, parent);
-                            break;
-                        default:
-                            break;
-                    }
-                } else if (oes != null){
-                    shape = new OLEShape(spContainer, parent);
-                }
-
-                if(shape == null) shape = new HSLFPictureShape(spContainer, parent);
+            case FRAME:
+                shape = createFrame(spContainer, parent);
                 break;
-            }
             case LINE:
                 shape = new HSLFLine(spContainer, parent);
                 break;
-            case NOT_PRIMITIVE: {
-                AbstractEscherOptRecord opt = HSLFShape.getEscherChild(spContainer, EscherOptRecord.RECORD_ID);
-                EscherProperty prop = HSLFShape.getEscherProperty(opt, EscherProperties.GEOMETRY__VERTICES);
-                if(prop != null)
-                    shape = new HSLFFreeformShape(spContainer, parent);
-                else {
-                    logger.log(POILogger.INFO, "Creating AutoShape for a NotPrimitive shape");
-                    shape = new HSLFAutoShape(spContainer, parent);
-                }
+            case NOT_PRIMITIVE:
+                shape = createNonPrimitive(spContainer, parent);
                 break;
-            }
             default:
-                shape = new HSLFAutoShape(spContainer, parent);
+                EscherTextboxRecord etr = spContainer.getChildById(EscherTextboxRecord.RECORD_ID);
+                if (parent instanceof HSLFTable && etr != null) {
+                    shape = new HSLFTableCell(spContainer, (HSLFTable)parent);
+                } else {
+                    shape = new HSLFAutoShape(spContainer, parent);
+                }
                 break;
         }
         return shape;
-
     }
 
+    private static HSLFShape createFrame(EscherContainerRecord spContainer, ShapeContainer<HSLFShape,HSLFTextParagraph> parent) {
+        InteractiveInfo info = getClientDataRecord(spContainer, RecordTypes.InteractiveInfo.typeID);
+        if(info != null && info.getInteractiveInfoAtom() != null){
+            switch(info.getInteractiveInfoAtom().getAction()){
+                case InteractiveInfoAtom.ACTION_OLE:
+                    return new OLEShape(spContainer, parent);
+                case InteractiveInfoAtom.ACTION_MEDIA:
+                    return new MovieShape(spContainer, parent);
+                default:
+                    break;
+            }
+        }
+        
+        OEShapeAtom oes = getClientDataRecord(spContainer, RecordTypes.OEShapeAtom.typeID);
+        if (oes != null){
+            return new OLEShape(spContainer, parent);
+        }
+
+        return new HSLFPictureShape(spContainer, parent);
+    }
+    
+    private static HSLFShape createNonPrimitive(EscherContainerRecord spContainer, ShapeContainer<HSLFShape,HSLFTextParagraph> parent) {
+        AbstractEscherOptRecord opt = HSLFShape.getEscherChild(spContainer, EscherOptRecord.RECORD_ID);
+        EscherProperty prop = HSLFShape.getEscherProperty(opt, EscherProperties.GEOMETRY__VERTICES);
+        if(prop != null) {
+            return new HSLFFreeformShape(spContainer, parent);
+        }
+        
+        logger.log(POILogger.INFO, "Creating AutoShape for a NotPrimitive shape");
+        return new HSLFAutoShape(spContainer, parent);
+    }
+    
     @SuppressWarnings("unchecked")
     protected static <T extends Record> T getClientDataRecord(EscherContainerRecord spContainer, int recordType) {
-        Record oep = null;
         for (Iterator<EscherRecord> it = spContainer.getChildIterator(); it.hasNext();) {
             EscherRecord obj = it.next();
             if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) {
                 byte[] data = obj.serialize();
-                Record[] records = Record.findChildRecords(data, 8, data.length - 8);
-                for (int j = 0; j < records.length; j++) {
-                    if (records[j].getRecordType() == recordType) {
-                        return (T)records[j];
+                for (Record r : Record.findChildRecords(data, 8, data.length - 8)) {
+                    if (r.getRecordType() == recordType) {
+                        return (T)r;
                     }
                 }
             }
         }
-        return (T)oep;
+        return null;
     }
 
 }

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSheet.java?rev=1711171&r1=1711170&r2=1711171&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSheet.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSheet.java Thu Oct 29 01:05:27 2015
@@ -458,7 +458,7 @@ public abstract class HSLFSheet implemen
             throw new IllegalArgumentException("numRows and numCols must be greater than 0");
         }
         HSLFTable s = new HSLFTable(numRows,numCols);
-        s.setAnchor(new Rectangle(0, 0, 100, 100));
+        // anchor is set in constructor based on numRows/numCols
         addShape(s);
         return s;
     }

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java?rev=1711171&r1=1711170&r2=1711171&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java Thu Oct 29 01:05:27 2015
@@ -27,6 +27,7 @@ import org.apache.poi.sl.draw.DrawPaint;
 import org.apache.poi.sl.draw.geom.*;
 import org.apache.poi.sl.usermodel.*;
 import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
+import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;
 import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;
 import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
 import org.apache.poi.util.LittleEndian;
@@ -147,11 +148,32 @@ public abstract class HSLFSimpleShape ex
     }
 
     /**
+     * Gets line cap.
+     *
+     * @return cap of the line.
+     */
+    public LineCap getLineCap(){
+        AbstractEscherOptRecord opt = getEscherOptRecord();
+        EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.LINESTYLE__LINEENDCAPSTYLE);
+        return (prop == null) ? LineCap.FLAT : LineCap.fromNativeId(prop.getPropertyValue());
+    }
+
+    /**
+     * Sets line cap.
+     *
+     * @param pen new style of the line.
+     */
+    public void setLineCap(LineCap pen){
+        AbstractEscherOptRecord opt = getEscherOptRecord();
+        setEscherProperty(opt, EscherProperties.LINESTYLE__LINEENDCAPSTYLE, pen == LineCap.FLAT ? -1 : pen.nativeId);
+    }
+    
+    /**
      * Gets line dashing.
      *
      * @return dashing of the line.
      */
-    public LineDash getLineDashing(){
+    public LineDash getLineDash(){
         AbstractEscherOptRecord opt = getEscherOptRecord();
         EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.LINESTYLE__LINEDASHING);
         return (prop == null) ? LineDash.SOLID : LineDash.fromNativeId(prop.getPropertyValue());
@@ -162,7 +184,7 @@ public abstract class HSLFSimpleShape ex
      *
      * @param pen new style of the line.
      */
-    public void setLineDashing(LineDash pen){
+    public void setLineDash(LineDash pen){
         AbstractEscherOptRecord opt = getEscherOptRecord();
         setEscherProperty(opt, EscherProperties.LINESTYLE__LINEDASHING, pen == LineDash.SOLID ? -1 : pen.nativeId);
     }
@@ -177,7 +199,7 @@ public abstract class HSLFSimpleShape ex
         EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.LINESTYLE__LINESTYLE);
         return (prop == null) ? LineCompound.SINGLE : LineCompound.fromNativeId(prop.getPropertyValue());
     }
-    
+
     /**
      * Sets the line compound style
      *
@@ -204,7 +226,7 @@ public abstract class HSLFSimpleShape ex
             }
 
             public LineDash getLineDash() {
-                return HSLFSimpleShape.this.getLineDashing();
+                return HSLFSimpleShape.this.getLineDash();
             }
 
             public LineCompound getLineCompound() {
@@ -214,23 +236,17 @@ public abstract class HSLFSimpleShape ex
             public double getLineWidth() {
                 return HSLFSimpleShape.this.getLineWidth();
             }
-            
+
         };
     }
 
-    /**
-     * The color used to fill this shape.
-     */
-    public Color getFillColor(){
+    @Override
+    public Color getFillColor() {
         return getFill().getForegroundColor();
     }
 
-    /**
-     * The color used to fill this shape.
-     *
-     * @param color the background color
-     */
-    public void setFillColor(Color color){
+    @Override
+    public void setFillColor(Color color) {
         getFill().setForegroundColor(color);
     }
 
@@ -353,10 +369,10 @@ public abstract class HSLFSimpleShape ex
         if (name == null || !name.matches("adj([1-9]|10)?")) {
             throw new IllegalArgumentException("Adjust value '"+name+"' not supported.");
         }
-        
+
         name = name.replace("adj", "");
         if ("".equals(name)) name = "1";
-        
+
         short escherProp;
         switch (Integer.parseInt(name)) {
             case 1: escherProp = EscherProperties.GEOMETRY__ADJUSTVALUE; break;
@@ -371,7 +387,7 @@ public abstract class HSLFSimpleShape ex
             case 10: escherProp = EscherProperties.GEOMETRY__ADJUST10VALUE; break;
             default: throw new RuntimeException();
         }
-        
+
         int adjval = getEscherProperty(escherProp, -1);
         return (adjval == -1) ? null : new Guide(name, "val "+adjval);
     }
@@ -386,7 +402,7 @@ public abstract class HSLFSimpleShape ex
             logger.log(POILogger.WARN, "No preset shape definition for shapeType: "+name);
             return null;
         }
-        
+
         return geom;
     }
 
@@ -399,7 +415,7 @@ public abstract class HSLFSimpleShape ex
         int offY = (prop == null) ? 0 : prop.getPropertyValue();
         return Math.toDegrees(Math.atan2(offY, offX));
     }
-    
+
     public double getShadowDistance() {
         AbstractEscherOptRecord opt = getEscherOptRecord();
         EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.SHADOWSTYLE__OFFSETX);
@@ -415,13 +431,13 @@ public abstract class HSLFSimpleShape ex
     public Color getShadowColor(){
         Color clr = getColor(EscherProperties.SHADOWSTYLE__COLOR, EscherProperties.SHADOWSTYLE__OPACITY, -1);
         return clr == null ? Color.black : clr;
-    }    
-    
+    }
+
     public Shadow<HSLFShape,HSLFTextParagraph> getShadow() {
         AbstractEscherOptRecord opt = getEscherOptRecord();
         EscherProperty shadowType = opt.lookup(EscherProperties.SHADOWSTYLE__TYPE);
         if (shadowType == null) return null;
-        
+
         return new Shadow<HSLFShape,HSLFTextParagraph>(){
             public SimpleShape<HSLFShape,HSLFTextParagraph> getShadowParent() {
                 return HSLFSimpleShape.this;
@@ -443,7 +459,7 @@ public abstract class HSLFSimpleShape ex
             public SolidPaint getFillStyle() {
                 return DrawPaint.createSolidPaint(getShadowColor());
             }
-            
+
         };
     }
 
@@ -475,4 +491,123 @@ public abstract class HSLFSimpleShape ex
             }
         };
     }
-}
+
+    protected void setPlaceholder(Placeholder placeholder) {
+        EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
+        int flags = spRecord.getFlags();
+        flags |= EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HAVEMASTER;
+        spRecord.setFlags(flags);
+
+        EscherClientDataRecord cldata = _escherContainer.getChildById(EscherClientDataRecord.RECORD_ID);
+        if (cldata == null) {
+            cldata = new EscherClientDataRecord();
+            // append placeholder container before EscherTextboxRecord
+            _escherContainer.addChildBefore(cldata, EscherTextboxRecord.RECORD_ID);
+        }
+        cldata.setOptions((short)15);
+
+        AbstractEscherOptRecord opt = getEscherOptRecord();
+
+        // Placeholders can't be grouped
+        setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 262144);
+
+        // OEPlaceholderAtom tells powerpoint that this shape is a placeholder
+        OEPlaceholderAtom oep = new OEPlaceholderAtom();
+
+        /**
+         * Extarct from MSDN:
+         *
+         * There is a special case when the placeholder does not have a position in the layout.
+         * This occurs when the user has moved the placeholder from its original position.
+         * In this case the placeholder ID is -1.
+         */
+        oep.setPlacementId(-1);
+
+        boolean isMaster = (getSheet() instanceof HSLFSlideMaster);
+        boolean isNotes = (getSheet() instanceof HSLFNotes);
+        byte phId;
+        switch (placeholder) {
+            case TITLE:
+                phId = (isMaster) ? OEPlaceholderAtom.MasterTitle : OEPlaceholderAtom.Title;
+                break;
+            case BODY:
+                phId = (isMaster) ? OEPlaceholderAtom.MasterBody :
+                    ((isNotes) ? OEPlaceholderAtom.NotesBody : OEPlaceholderAtom.Body);
+                break;
+            case CENTERED_TITLE:
+                phId = (isMaster) ? OEPlaceholderAtom.MasterCenteredTitle : OEPlaceholderAtom.CenteredTitle;
+                break;
+            case SUBTITLE:
+                phId = (isMaster) ? OEPlaceholderAtom.MasterSubTitle : OEPlaceholderAtom.Subtitle;
+                break;
+            case DATETIME:
+                phId = OEPlaceholderAtom.MasterDate;
+                break;
+            case SLIDE_NUMBER:
+                phId = OEPlaceholderAtom.MasterSlideNumber;
+                break;
+            case FOOTER:
+                phId = OEPlaceholderAtom.MasterFooter;
+                break;
+            case HEADER:
+                phId = OEPlaceholderAtom.MasterHeader;
+                break;
+            case DGM:
+            case CHART:
+                phId = OEPlaceholderAtom.Graph;
+                break;
+            case TABLE:
+                phId = OEPlaceholderAtom.Table;
+                break;
+            case PICTURE:
+            case CLIP_ART:
+                phId = OEPlaceholderAtom.ClipArt;
+                break;
+            case MEDIA:
+                phId = OEPlaceholderAtom.MediaClip;
+                break;
+            case SLIDE_IMAGE:
+                phId = (isMaster) ? OEPlaceholderAtom.MasterNotesSlideImage : OEPlaceholderAtom.NotesSlideImage;
+                break;
+            default:
+            case CONTENT:
+                phId = OEPlaceholderAtom.Object;
+                break;
+        }
+        oep.setPlaceholderId(phId);
+
+        //convert hslf into ddf record
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        try {
+            oep.writeOut(out);
+        } catch(Exception e){
+            throw new HSLFException(e);
+        }
+        cldata.setRemainingData(out.toByteArray());
+    }
+
+
+    @Override
+    public void setStrokeStyle(Object... styles) {
+        if (styles.length == 0) {
+            // remove stroke
+            setLineColor(null);
+            return;
+        }
+        
+        // TODO: handle PaintStyle
+        for (Object st : styles) {
+            if (st instanceof Number) {
+                setLineWidth(((Number)st).doubleValue());
+            } else if (st instanceof LineCap) {
+                setLineCap((LineCap)st);
+            } else if (st instanceof LineDash) {
+                setLineDash((LineDash)st);
+            } else if (st instanceof LineCompound) {
+                setLineCompound((LineCompound)st);
+            } else if (st instanceof Color) {
+                setLineColor((Color)st);
+            }
+        }
+    }
+}
\ No newline at end of file

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java?rev=1711171&r1=1711170&r2=1711171&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java Thu Oct 29 01:05:27 2015
@@ -27,7 +27,6 @@ import org.apache.poi.ddf.EscherDggRecor
 import org.apache.poi.ddf.EscherSpRecord;
 import org.apache.poi.hslf.model.Comment;
 import org.apache.poi.hslf.model.HeadersFooters;
-import org.apache.poi.hslf.model.Placeholder;
 import org.apache.poi.hslf.record.ColorSchemeAtom;
 import org.apache.poi.hslf.record.Comment2000;
 import org.apache.poi.hslf.record.EscherTextboxWrapper;
@@ -196,7 +195,7 @@ public final class HSLFSlide extends HSL
 	 * @return <code>TextBox</code> object that represents the slide's title.
 	 */
 	public HSLFTextBox addTitle() {
-		Placeholder pl = new Placeholder();
+		HSLFPlaceholder pl = new HSLFPlaceholder();
 		pl.setShapeType(ShapeType.RECT);
 		pl.setRunType(TextHeaderAtom.TITLE_TYPE);
 		pl.setText("Click to edit title");

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java?rev=1711171&r1=1711170&r2=1711171&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java Thu Oct 29 01:05:27 2015
@@ -531,9 +531,7 @@ public final class HSLFSlideShow impleme
 		return HSLFSoundData.find(_documentRecord);
 	}
 
-	/**
-	 * Return the current page size
-	 */
+	@Override
 	public Dimension getPageSize() {
 		DocumentAtom docatom = _documentRecord.getDocumentAtom();
 		int pgx = (int)Units.masterToPoints((int)docatom.getSlideSizeX());
@@ -541,12 +539,7 @@ public final class HSLFSlideShow impleme
 		return new Dimension(pgx, pgy);
 	}
 
-	/**
-	 * Change the current page size
-	 *
-	 * @param pgsize
-	 *            page size (in points)
-	 */
+	@Override
 	public void setPageSize(Dimension pgsize) {
 		DocumentAtom docatom = _documentRecord.getDocumentAtom();
 		docatom.setSlideSizeX(Units.pointsToMaster(pgsize.width));

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java?rev=1711171&r1=1711170&r2=1711171&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java Thu Oct 29 01:05:27 2015
@@ -21,17 +21,16 @@ import java.awt.Rectangle;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.Iterator;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.poi.ddf.AbstractEscherOptRecord;
 import org.apache.poi.ddf.EscherArrayProperty;
 import org.apache.poi.ddf.EscherContainerRecord;
 import org.apache.poi.ddf.EscherOptRecord;
 import org.apache.poi.ddf.EscherProperties;
-import org.apache.poi.ddf.EscherRecord;
 import org.apache.poi.ddf.EscherSimpleProperty;
-import org.apache.poi.ddf.EscherTextboxRecord;
 import org.apache.poi.hslf.record.RecordTypes;
 import org.apache.poi.sl.usermodel.ShapeContainer;
 import org.apache.poi.sl.usermodel.TableShape;
@@ -46,11 +45,6 @@ import org.apache.poi.util.Units;
 public final class HSLFTable extends HSLFGroupShape
 implements HSLFShapeContainer, TableShape<HSLFShape,HSLFTextParagraph> {
 
-    protected static final int BORDER_TOP = 1;
-    protected static final int BORDER_RIGHT = 2;
-    protected static final int BORDER_BOTTOM = 3;
-    protected static final int BORDER_LEFT = 4;
-
     protected static final int BORDERS_ALL = 5;
     protected static final int BORDERS_OUTSIDE = 6;
     protected static final int BORDERS_INSIDE = 7;
@@ -65,10 +59,10 @@ implements HSLFShapeContainer, TableShap
      * @param numRows the number of rows
      * @param numCols the number of columns
      */
-    public HSLFTable(int numRows, int numCols) {
+    protected HSLFTable(int numRows, int numCols) {
         this(numRows, numCols, null);
     }
-    
+
     /**
      * Create a new Table of the given number of rows and columns
      *
@@ -76,7 +70,7 @@ implements HSLFShapeContainer, TableShap
      * @param numCols the number of columns
      * @param parent the parent shape, or null if table is added to sheet
      */
-    public HSLFTable(int numRows, int numCols, ShapeContainer<HSLFShape,HSLFTextParagraph> parent) {
+    protected HSLFTable(int numRows, int numCols, ShapeContainer<HSLFShape,HSLFTextParagraph> parent) {
         super(parent);
 
         if(numRows < 1) throw new IllegalArgumentException("The number of rows must be greater than 1");
@@ -96,13 +90,13 @@ implements HSLFShapeContainer, TableShap
         }
         tblWidth = x;
         tblHeight = y;
-        setAnchor(new Rectangle(0, 0, tblWidth, tblHeight));
+        setExteriorAnchor(new Rectangle(0, 0, tblWidth, tblHeight));
 
         EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0);
         AbstractEscherOptRecord opt = new EscherOptRecord();
         opt.setRecordId((short)RecordTypes.EscherUserDefined);
-        opt.addEscherProperty(new EscherSimpleProperty((short)0x39F, 1));
-        EscherArrayProperty p = new EscherArrayProperty((short)(0x4000 | 0x3A0), false, null);
+        opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__TABLEPROPERTIES, 1));
+        EscherArrayProperty p = new EscherArrayProperty((short)(0x4000 | EscherProperties.GROUPSHAPE__TABLEROWPROPERTIES), false, null);
         p.setSizeOfElements(0x0004);
         p.setNumberOfElementsInArray(numRows);
         p.setNumberOfElementsInMemory(numRows);
@@ -111,12 +105,12 @@ implements HSLFShapeContainer, TableShap
     }
 
     /**
-     * Create a Table object and initilize it from the supplied Record container.
+     * Create a Table 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
      */
-    public HSLFTable(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape,HSLFTextParagraph> parent) {
+    protected HSLFTable(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape,HSLFTextParagraph> parent) {
         super(escherRecord, parent);
     }
 
@@ -131,9 +125,12 @@ implements HSLFShapeContainer, TableShap
         return cells[row][col];
     }
 
+    @Override
     public int getNumberOfColumns() {
         return cells[0].length;
     }
+
+    @Override
     public int getNumberOfRows() {
         return cells.length;
     }
@@ -141,90 +138,171 @@ implements HSLFShapeContainer, TableShap
     protected void afterInsert(HSLFSheet sh){
         super.afterInsert(sh);
 
-        EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0);
-        List<EscherRecord> lst = spCont.getChildRecords();
-        AbstractEscherOptRecord opt = (AbstractEscherOptRecord)lst.get(lst.size()-2);
-        EscherArrayProperty p = opt.lookup(0x3A0); 
-        for (int i = 0; i < cells.length; i++) {
-            HSLFTableCell cell = cells[i][0];
-            int rowHeight = Units.pointsToMaster(cell.getAnchor().height);
-            byte[] val = new byte[4];
-            LittleEndian.putInt(val, 0, rowHeight);
-            p.setElement(i, val);
-            for (int j = 0; j < cells[i].length; j++) {
-                HSLFTableCell c = cells[i][j];
+        Set<HSLFLine> lineSet = new HashSet<HSLFLine>();
+        for (HSLFTableCell row[] : cells) {
+            for (HSLFTableCell c : row) {
                 addShape(c);
+                for (HSLFLine bt : new HSLFLine[]{ c.borderTop, c.borderRight, c.borderBottom, c.borderLeft }) {
+                    if (bt != null) {
+                        lineSet.add(bt);
+                    }
+                }
+            }
+        }
+
+        for (HSLFLine l : lineSet) {
+            addShape(l);
+        }
 
-                HSLFLine bt = c.getBorderTop();
-                if(bt != null) addShape(bt);
+        updateRowHeightsProperty();
+    }
+
+    private static class TableCellComparator implements Comparator<HSLFShape> {
+        public int compare( HSLFShape o1, HSLFShape o2 ) {
+            Rectangle anchor1 = o1.getAnchor();
+            Rectangle anchor2 = o2.getAnchor();
+            int delta = anchor1.y - anchor2.y;
+            if (delta == 0) delta = anchor1.x - anchor2.x;
+            // descending size
+            if (delta == 0) delta = (anchor2.width*anchor2.height)-(anchor1.width*anchor1.height);
+            return delta;
+        }
+    }
 
-                HSLFLine br = c.getBorderRight();
-                if(br != null) addShape(br);
+    private void cellListToArray() {
+        List<HSLFTableCell> htc = new ArrayList<HSLFTableCell>();
+        for (HSLFShape h : getShapes()) {
+            if (h instanceof HSLFTableCell) {
+                htc.add((HSLFTableCell)h);
+            }
+        }
+        
+        if (htc.isEmpty()) {
+            throw new IllegalStateException("HSLFTable without HSLFTableCells");
+        }
 
-                HSLFLine bb = c.getBorderBottom();
-                if(bb != null) addShape(bb);
+        Collections.sort(htc, new TableCellComparator());
 
-                HSLFLine bl = c.getBorderLeft();
-                if(bl != null) addShape(bl);
+        List<HSLFTableCell[]> lst = new ArrayList<HSLFTableCell[]>();
+        List<HSLFTableCell> row = new ArrayList<HSLFTableCell>();
 
+        int y0 = htc.get(0).getAnchor().y;
+        for (HSLFTableCell sh : htc) {
+            Rectangle anchor = sh.getAnchor();
+            boolean isNextRow = (anchor.y > y0);
+            if (isNextRow) {
+                y0 = anchor.y;
+                lst.add(row.toArray(new HSLFTableCell[row.size()]));
+                row.clear();
             }
+            row.add(sh);
         }
+        lst.add(row.toArray(new HSLFTableCell[row.size()]));
 
+        cells = lst.toArray(new HSLFTableCell[lst.size()][]);
     }
 
-    protected void initTable(){
-        List<HSLFShape> shapeList = getShapes();
+    static class LineRect {
+        final HSLFLine l;
+        final double lx1, lx2, ly1, ly2;
+        LineRect(HSLFLine l) {
+            this.l = l;
+            Rectangle r = l.getAnchor();
+            lx1 = r.getMinX();
+            lx2 = r.getMaxX();
+            ly1 = r.getMinY();
+            ly2 = r.getMaxY();
+        }
+        int leftFit(double x1, double x2, double y1, double y2) {
+            return (int)(Math.abs(x1-lx1)+Math.abs(y1-ly1)+Math.abs(x1-lx2)+Math.abs(y2-ly2));
+        }
+        int topFit(double x1, double x2, double y1, double y2) {
+            return (int)(Math.abs(x1-lx1)+Math.abs(y1-ly1)+Math.abs(x2-lx2)+Math.abs(y1-ly2));
+        }
+        int rightFit(double x1, double x2, double y1, double y2) {
+            return (int)(Math.abs(x2-lx1)+Math.abs(y1-ly1)+Math.abs(x2-lx2)+Math.abs(y2-ly2));
+        }
+        int bottomFit(double x1, double x2, double y1, double y2) {
+            return (int)(Math.abs(x1-lx1)+Math.abs(y2-ly1)+Math.abs(x2-lx2)+Math.abs(y2-ly2));
+        }
+    }
 
-        Iterator<HSLFShape> shapeIter = shapeList.iterator();
-        while (shapeIter.hasNext()) {
-            HSLFShape shape = shapeIter.next();
-            if (shape instanceof HSLFAutoShape) {
-                HSLFAutoShape autoShape = (HSLFAutoShape)shape;
-                EscherTextboxRecord etr = autoShape.getEscherChild(EscherTextboxRecord.RECORD_ID);
-                if (etr != null) continue;
-            }
-            shapeIter.remove();
-        }        
-        
-        Collections.sort(shapeList, new Comparator<HSLFShape>(){
-            public int compare( HSLFShape o1, HSLFShape o2 ) {
-                Rectangle anchor1 = o1.getAnchor();
-                Rectangle anchor2 = o2.getAnchor();
-                int delta = anchor1.y - anchor2.y;
-                if (delta == 0) delta = anchor1.x - anchor2.x;
-                // descending size
-                if (delta == 0) delta = (anchor2.width*anchor2.height)-(anchor1.width*anchor1.height);
-                return delta;
-            }
-        });
-        
-        int y0 = (shapeList.isEmpty()) ? -1 : shapeList.get(0).getAnchor().y - 1;
-        int maxrowlen = 0;
-        List<List<HSLFShape>> lst = new ArrayList<List<HSLFShape>>();
-        List<HSLFShape> row = null;
-        for (HSLFShape sh : shapeList) {
-            if(sh instanceof HSLFTextShape){
-                Rectangle anchor = sh.getAnchor();
-                if(anchor.y != y0){
-                    y0 = anchor.y;
-                    row = new ArrayList<HSLFShape>();
-                    lst.add(row);
-                }
-                row.add(sh);
-                maxrowlen = Math.max(maxrowlen, row.size());
+    private void fitLinesToCells() {
+        List<LineRect> lines = new ArrayList<LineRect>();
+        for (HSLFShape h : getShapes()) {
+            if (h instanceof HSLFLine) {
+                lines.add(new LineRect((HSLFLine)h));
             }
         }
-        cells = new HSLFTableCell[lst.size()][maxrowlen];
-        for (int i = 0; i < lst.size(); i++) {
-            row = lst.get(i);
-            for (int j = 0; j < row.size(); j++) {
-                HSLFTextShape tx = (HSLFTextShape)row.get(j);
-                cells[i][j] = new HSLFTableCell(tx.getSpContainer(), getParent());
-                cells[i][j].setSheet(tx.getSheet());
+
+        final int threshold = 5;
+
+        // TODO: this only works for non-rotated tables
+        for (HSLFTableCell[] tca : cells) {
+            for (HSLFTableCell tc : tca) {
+                final Rectangle cellAnchor = tc.getAnchor();
+
+                /**
+                 * x1/y1 --------+
+                 *   |           |
+                 *   +---------x2/y2
+                 */
+                final double x1 = cellAnchor.getMinX();
+                final double x2 = cellAnchor.getMaxX();
+                final double y1 = cellAnchor.getMinY();
+                final double y2 = cellAnchor.getMaxY();
+
+                LineRect lline = null, tline = null, rline = null, bline = null;
+                int lfit = Integer.MAX_VALUE, tfit = Integer.MAX_VALUE, rfit = Integer.MAX_VALUE, bfit = Integer.MAX_VALUE;
+
+                for (LineRect lr : lines) {
+                    // calculate border fit
+                    int lfitx = lr.leftFit(x1, x2, y1, y2);
+                    if (lfitx < lfit) {
+                        lfit = lfitx;
+                        lline = lr;
+                    }
+
+                    int tfitx = lr.topFit(x1, x2, y1, y2);
+                    if (tfitx < tfit) {
+                        tfit = tfitx;
+                        tline = lr;
+                    }
+
+                    int rfitx = lr.rightFit(x1, x2, y1, y2);
+                    if (rfitx < rfit) {
+                        rfit = rfitx;
+                        rline = lr;
+                    }
+
+                    int bfitx = lr.bottomFit(x1, x2, y1, y2);
+                    if (bfitx < bfit) {
+                        bfit = bfitx;
+                        bline = lr;
+                    }
+                }
+
+                if (lfit < threshold) {
+                    tc.borderLeft = lline.l;
+                }
+                if (tfit < threshold) {
+                    tc.borderTop = tline.l;
+                }
+                if (rfit < threshold) {
+                    tc.borderRight = rline.l;
+                }
+                if (bfit < threshold) {
+                    tc.borderBottom = bline.l;
+                }
             }
         }
     }
 
+    protected void initTable(){
+        cellListToArray();
+        fitLinesToCells();
+    }
+
     /**
      * Assign the <code>SlideShow</code> this shape belongs to
      *
@@ -232,151 +310,102 @@ implements HSLFShapeContainer, TableShap
      */
     public void setSheet(HSLFSheet sheet){
         super.setSheet(sheet);
-        if(cells == null) initTable();
+        if (cells == null) {
+            initTable();
+        } else {
+            for (HSLFTableCell cols[] : cells) {
+                for (HSLFTableCell col : cols) {
+                    col.setSheet(sheet);
+                }
+            }
+        }
     }
 
-    /**
-     * Sets the row height.
-     *
-     * @param row the row index (0-based)
-     * @param height the height to set (in pixels)
-     */
-    public void setRowHeight(int row, int height){
+    @Override
+    public void setRowHeight(int row, double height) {
+        int pxHeight = Units.pointsToPixel(height);
         int currentHeight = cells[row][0].getAnchor().height;
-        int dy = height - currentHeight;
+        int dy = pxHeight - currentHeight;
 
         for (int i = row; i < cells.length; i++) {
             for (int j = 0; j < cells[i].length; j++) {
                 Rectangle anchor = cells[i][j].getAnchor();
-                if(i == row) anchor.height = height;
-                else anchor.y += dy;
+                if(i == row) {
+                    anchor.height = pxHeight;
+                } else {
+                    anchor.y += dy;
+                }
                 cells[i][j].setAnchor(anchor);
             }
         }
         Rectangle tblanchor = getAnchor();
         tblanchor.height += dy;
-        setAnchor(tblanchor);
+        setExteriorAnchor(tblanchor);
 
     }
 
-    /**
-     * Sets the column width.
-     *
-     * @param col the column index (0-based)
-     * @param width the width to set (in pixels)
-     */
-    public void setColumnWidth(int col, int width){
-        int currentWidth = cells[0][col].getAnchor().width;
-        int dx = width - currentWidth;
-        for (int i = 0; i < cells.length; i++) {
-            Rectangle anchor = cells[i][col].getAnchor();
-            anchor.width = width;
-            cells[i][col].setAnchor(anchor);
-
-            if(col < cells[i].length - 1) for (int j = col+1; j < cells[i].length; j++) {
-                anchor = cells[i][j].getAnchor();
-                anchor.x += dx;
-                cells[i][j].setAnchor(anchor);
+    @Override
+    public void setColumnWidth(int col, final double width){
+        if (col < 0 || col >= cells[0].length) {
+            throw new IllegalArgumentException("Column index '"+col+"' is not within range [0-"+(cells[0].length-1)+"]");
+        }
+        double currentWidth = cells[0][col].getAnchor().getWidth();
+        double dx = width - currentWidth;
+        for (HSLFTableCell cols[] : cells) {
+            Rectangle anchor = cols[col].getAnchor();
+            anchor.width = (int)Math.rint(width);
+            cols[col].setAnchor(anchor);
+
+            if (col < cols.length - 1) {
+                for (int j = col+1; j < cols.length; j++) {
+                    anchor = cols[j].getAnchor();
+                    anchor.x += dx;
+                    cols[j].setAnchor(anchor);
+                }
             }
         }
         Rectangle tblanchor = getAnchor();
         tblanchor.width += dx;
-        setAnchor(tblanchor);
+        setExteriorAnchor(tblanchor);
     }
 
-    /**
-     * Format the table and apply the specified Line to all cell boundaries,
-     * both outside and inside
-     *
-     * @param line the border line
-     */
-    public void setAllBorders(HSLFLine line){
-        for (int i = 0; i < cells.length; i++) {
-            for (int j = 0; j < cells[i].length; j++) {
-                HSLFTableCell cell = cells[i][j];
-                cell.setBorderTop(cloneBorder(line));
-                cell.setBorderLeft(cloneBorder(line));
-                if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line));
-                if(i == cells.length - 1) cell.setBorderBottom(cloneBorder(line));
-            }
-        }
-    }
-
-    /**
-     * Format the outside border using the specified Line object
-     *
-     * @param line the border line
-     */
-    public void setOutsideBorders(HSLFLine line){
-        for (int i = 0; i < cells.length; i++) {
-            for (int j = 0; j < cells[i].length; j++) {
-                HSLFTableCell cell = cells[i][j];
-
-                if(j == 0) cell.setBorderLeft(cloneBorder(line));
-                if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line));
-                else {
-                    cell.setBorderLeft(null);
-                    cell.setBorderLeft(null);
-                }
-
-                if(i == 0) cell.setBorderTop(cloneBorder(line));
-                else if(i == cells.length - 1) cell.setBorderBottom(cloneBorder(line));
-                else {
-                    cell.setBorderTop(null);
-                    cell.setBorderBottom(null);
+    protected HSLFTableCell getRelativeCell(HSLFTableCell origin, int row, int col) {
+        int thisRow = 0, thisCol = 0;
+        boolean found = false;
+        outer: for (HSLFTableCell[] tca : cells) {
+            thisCol = 0;
+            for (HSLFTableCell tc : tca) {
+                if (tc == origin) {
+                    found = true;
+                    break outer;
                 }
+                thisCol++;
             }
+            thisRow++;
         }
-    }
-
-    /**
-     * Format the inside border using the specified Line object
-     *
-     * @param line the border line
-     */
-    public void setInsideBorders(HSLFLine line){
-        for (int i = 0; i < cells.length; i++) {
-            for (int j = 0; j < cells[i].length; j++) {
-                HSLFTableCell cell = cells[i][j];
 
-                if(j != cells[i].length - 1)
-                    cell.setBorderRight(cloneBorder(line));
-                else {
-                    cell.setBorderLeft(null);
-                    cell.setBorderLeft(null);
-                }
-                if(i != cells.length - 1) cell.setBorderBottom(cloneBorder(line));
-                else {
-                    cell.setBorderTop(null);
-                    cell.setBorderBottom(null);
-                }
-            }
-        }
+        int otherRow = thisRow + row;
+        int otherCol = thisCol + col;
+        return (found
+            && 0 <= otherRow && otherRow < cells.length
+            && 0 <= otherCol && otherCol < cells[otherRow].length)
+            ? cells[otherRow][otherCol] : null;
     }
 
-    private HSLFLine cloneBorder(HSLFLine line){
-        HSLFLine border = createBorder();
-        border.setLineWidth(line.getLineWidth());
-        border.setLineDashing(line.getLineDashing());
-        border.setLineColor(line.getLineColor());
-        border.setLineCompound(line.getLineCompound());
-        return border;
+    @Override
+    protected void moveAndScale(Rectangle anchorDest){
+        super.moveAndScale(anchorDest);
+        updateRowHeightsProperty();
     }
 
-    /**
-     * Create a border to format this table
-     *
-     * @return the created border
-     */
-    public HSLFLine createBorder(){
-        HSLFLine line = new HSLFLine(this);
-
+    private void updateRowHeightsProperty() {
         AbstractEscherOptRecord opt = getEscherOptRecord();
-        setEscherProperty(opt, EscherProperties.GEOMETRY__SHAPEPATH, -1);
-        setEscherProperty(opt, EscherProperties.GEOMETRY__FILLOK, -1);
-        setEscherProperty(opt, EscherProperties.SHADOWSTYLE__SHADOWOBSURED, 0x20000);
-        setEscherProperty(opt, EscherProperties.THREED__LIGHTFACE, 0x80000);
-
-        return line;
+        EscherArrayProperty p = opt.lookup(EscherProperties.GROUPSHAPE__TABLEROWPROPERTIES);
+        byte[] val = new byte[4];
+        for (int rowIdx = 0; rowIdx < cells.length; rowIdx++) {
+            int rowHeight = Units.pointsToMaster(cells[rowIdx][0].getAnchor().height);
+            LittleEndian.putInt(val, 0, rowHeight);
+            p.setElement(rowIdx, val);
+        }
     }
 }

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTableCell.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTableCell.java?rev=1711171&r1=1711170&r2=1711171&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTableCell.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTableCell.java Thu Oct 29 01:05:27 2015
@@ -17,13 +17,18 @@
 
 package org.apache.poi.hslf.usermodel;
 
+import java.awt.Color;
 import java.awt.Rectangle;
 
 import org.apache.poi.ddf.AbstractEscherOptRecord;
 import org.apache.poi.ddf.EscherContainerRecord;
 import org.apache.poi.ddf.EscherProperties;
-import org.apache.poi.sl.usermodel.ShapeContainer;
+import org.apache.poi.sl.draw.DrawPaint;
+import org.apache.poi.sl.usermodel.PaintStyle;
 import org.apache.poi.sl.usermodel.ShapeType;
+import org.apache.poi.sl.usermodel.StrokeStyle;
+import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;
+import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
 import org.apache.poi.sl.usermodel.TableCell;
 
 /**
@@ -35,10 +40,10 @@ public final class HSLFTableCell extends
     protected static final int DEFAULT_WIDTH = 100;
     protected static final int DEFAULT_HEIGHT = 40;
 
-    private HSLFLine borderLeft;
-    private HSLFLine borderRight;
-    private HSLFLine borderTop;
-    private HSLFLine borderBottom;
+    /* package */ HSLFLine borderLeft;
+    /* package */ HSLFLine borderRight;
+    /* package */ HSLFLine borderTop;
+    /* package */ HSLFLine borderBottom;
 
     /**
      * Create a TableCell object and initialize it from the supplied Record container.
@@ -46,7 +51,7 @@ public final class HSLFTableCell extends
      * @param escherRecord       EscherSpContainer which holds information about this shape
      * @param parent    the parent of the shape
      */
-   protected HSLFTableCell(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
+   protected HSLFTableCell(EscherContainerRecord escherRecord, HSLFTable parent){
         super(escherRecord, parent);
     }
 
@@ -56,7 +61,7 @@ public final class HSLFTableCell extends
      * @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 HSLFTableCell(ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
+    public HSLFTableCell(HSLFTable parent){
         super(parent);
 
         setShapeType(ShapeType.RECT);
@@ -76,82 +81,320 @@ public final class HSLFTableCell extends
         return _escherContainer;
     }
 
-    protected void anchorBorder(int type, HSLFLine line){
+    private void anchorBorder(BorderEdge edge, final HSLFLine line) {
+        if (line == null) {
+            return;
+        }
         Rectangle cellAnchor = getAnchor();
         Rectangle lineAnchor = new Rectangle();
-        switch(type){
-            case HSLFTable.BORDER_TOP:
+        switch(edge){
+            case top:
                 lineAnchor.x = cellAnchor.x;
                 lineAnchor.y = cellAnchor.y;
                 lineAnchor.width = cellAnchor.width;
                 lineAnchor.height = 0;
                 break;
-            case HSLFTable.BORDER_RIGHT:
+            case right:
                 lineAnchor.x = cellAnchor.x + cellAnchor.width;
                 lineAnchor.y = cellAnchor.y;
                 lineAnchor.width = 0;
                 lineAnchor.height = cellAnchor.height;
                 break;
-            case HSLFTable.BORDER_BOTTOM:
+            case bottom:
                 lineAnchor.x = cellAnchor.x;
                 lineAnchor.y = cellAnchor.y + cellAnchor.height;
                 lineAnchor.width = cellAnchor.width;
                 lineAnchor.height = 0;
                 break;
-            case HSLFTable.BORDER_LEFT:
+            case left:
                 lineAnchor.x = cellAnchor.x;
                 lineAnchor.y = cellAnchor.y;
                 lineAnchor.width = 0;
                 lineAnchor.height = cellAnchor.height;
                 break;
             default:
-                throw new IllegalArgumentException("Unknown border type: " + type);
+                throw new IllegalArgumentException();
         }
         line.setAnchor(lineAnchor);
     }
 
-    public HSLFLine getBorderLeft() {
-        return borderLeft;
+    public void setAnchor(Rectangle anchor){
+        super.setAnchor(anchor);
+
+        anchorBorder(BorderEdge.top, borderTop);
+        anchorBorder(BorderEdge.right, borderRight);
+        anchorBorder(BorderEdge.bottom, borderBottom);
+        anchorBorder(BorderEdge.left, borderLeft);
+    }
+
+    @Override
+    public StrokeStyle getBorderStyle(final BorderEdge edge) {
+        final Double width = getBorderWidth(edge); 
+        return (width == null) ? null : new StrokeStyle() {
+            public PaintStyle getPaint() {
+                return DrawPaint.createSolidPaint(getBorderColor(edge));
+            }
+
+            public LineCap getLineCap() {
+                return null;
+            }
+
+            public LineDash getLineDash() {
+                return getBorderDash(edge);
+            }
+
+            public LineCompound getLineCompound() {
+                return getBorderCompound(edge);
+            }
+
+            public double getLineWidth() {
+                return width;
+            }
+        };
+    }
+
+    @Override
+    public void setBorderStyle(BorderEdge edge, StrokeStyle style) {
+        if (style == null) {
+            throw new IllegalArgumentException("StrokeStyle needs to be specified.");
+        }
+        
+        // setting the line cap is not implemented, as the border lines aren't connected
+        
+        LineCompound compound = style.getLineCompound();
+        if (compound != null) {
+            setBorderCompound(edge, compound);
+        }
+        
+        LineDash dash = style.getLineDash();
+        if (dash != null) {
+            setBorderDash(edge, dash);
+        }
+        
+        double width = style.getLineWidth();
+        setBorderWidth(edge, width);
     }
 
-    public void setBorderLeft(HSLFLine line) {
-        if(line != null) anchorBorder(HSLFTable.BORDER_LEFT, line);
-        this.borderLeft = line;
+    
+    public Double getBorderWidth(BorderEdge edge) {
+        HSLFLine l;
+        switch (edge) {
+            case bottom: l = borderBottom; break;
+            case top: l = borderTop; break;
+            case right: l = borderRight; break;
+            case left: l = borderLeft; break;
+            default: throw new IllegalArgumentException();
+        }
+        return (l == null) ? null : l.getLineWidth();
+    }
+    
+    @Override
+    public void setBorderWidth(BorderEdge edge, double width) {
+        HSLFLine l = addLine(edge);
+        l.setLineWidth(width);
+    }
+
+    public Color getBorderColor(BorderEdge edge) {
+        HSLFLine l;
+        switch (edge) {
+            case bottom: l = borderBottom; break;
+            case top: l = borderTop; break;
+            case right: l = borderRight; break;
+            case left: l = borderLeft; break;
+            default: throw new IllegalArgumentException();
+        }
+        return (l == null) ? null : l.getLineColor();
     }
 
-    public HSLFLine getBorderRight() {
-        return borderRight;
+    @Override
+    public void setBorderColor(BorderEdge edge, Color color) {
+        if (edge == null || color == null) {
+            throw new IllegalArgumentException("BorderEdge and/or Color need to be specified.");
+        }
+        
+        HSLFLine l = addLine(edge);
+        l.setLineColor(color);
     }
 
-    public void setBorderRight(HSLFLine line) {
-        if(line != null) anchorBorder(HSLFTable.BORDER_RIGHT, line);
-        this.borderRight = line;
+    public LineDash getBorderDash(BorderEdge edge) {
+        HSLFLine l;
+        switch (edge) {
+            case bottom: l = borderBottom; break;
+            case top: l = borderTop; break;
+            case right: l = borderRight; break;
+            case left: l = borderLeft; break;
+            default: throw new IllegalArgumentException();
+        }
+        return (l == null) ? null : l.getLineDash();        
+    }
+    
+    @Override
+    public void setBorderDash(BorderEdge edge, LineDash dash) {
+        if (edge == null || dash == null) {
+            throw new IllegalArgumentException("BorderEdge and/or LineDash need to be specified.");
+        }
+        
+        HSLFLine l = addLine(edge);
+        l.setLineDash(dash);
+    }
+
+    public LineCompound getBorderCompound(BorderEdge edge) {
+        HSLFLine l;
+        switch (edge) {
+            case bottom: l = borderBottom; break;
+            case top: l = borderTop; break;
+            case right: l = borderRight; break;
+            case left: l = borderLeft; break;
+            default: throw new IllegalArgumentException();
+        }
+        return (l == null) ? null : l.getLineCompound();        
+    }
+    
+    @Override
+    public void setBorderCompound(BorderEdge edge, LineCompound compound) {
+        if (edge == null || compound == null) {
+            throw new IllegalArgumentException("BorderEdge and/or LineCompound need to be specified.");
+        }
+        
+        HSLFLine l = addLine(edge);
+        l.setLineCompound(compound);
     }
 
-    public HSLFLine getBorderTop() {
-        return borderTop;
+
+    protected HSLFLine addLine(BorderEdge edge) {
+        switch (edge) {
+            case bottom: {
+                if (borderBottom == null) {
+                    borderBottom = createBorder(edge);
+                    HSLFTableCell c = getSiblingCell(1,0);
+                    if (c != null) {
+                        assert(c.borderTop == null);
+                        c.borderTop = borderBottom;
+                    }
+                }
+                return borderBottom;
+            }
+            case top: {
+                if (borderTop == null) {
+                    borderTop = createBorder(edge);
+                    HSLFTableCell c = getSiblingCell(-1,0);
+                    if (c != null) {
+                        assert(c.borderBottom == null);
+                        c.borderBottom = borderTop;
+                    }
+                }
+                return borderTop;
+            }
+            case right: {
+                if (borderRight == null) {
+                    borderRight = createBorder(edge);
+                    HSLFTableCell c = getSiblingCell(0,1);
+                    if (c != null) {
+                        assert(c.borderLeft == null);
+                        c.borderLeft = borderRight;
+                    }
+                }
+                return borderRight;
+            }
+            case left: {
+                if (borderLeft == null) {
+                    borderLeft = createBorder(edge);
+                    HSLFTableCell c = getSiblingCell(0,-1);
+                    if (c != null) {
+                        assert(c.borderRight == null);
+                        c.borderRight = borderLeft;
+                    }
+                }
+                return borderLeft;
+            }
+            default:
+                throw new IllegalArgumentException();
+        }
     }
 
-    public void setBorderTop(HSLFLine line) {
-        if(line != null) anchorBorder(HSLFTable.BORDER_TOP, line);
-        this.borderTop = line;
+    @Override
+    public void removeBorder(BorderEdge edge) {
+        switch (edge) {
+            case bottom: {
+                if (borderBottom == null) break;
+                getParent().removeShape(borderBottom);
+                borderBottom = null;
+                HSLFTableCell c = getSiblingCell(1,0);
+                if (c != null) {
+                    c.borderTop = null;
+                }
+                break;
+            }
+            case top: {
+                if (borderTop == null) break;
+                getParent().removeShape(borderTop);
+                borderTop = null;
+                HSLFTableCell c = getSiblingCell(-1,0);
+                if (c != null) {
+                    c.borderBottom = null;
+                }
+                break;
+            }
+            case right: {
+                if (borderRight == null) break;
+                getParent().removeShape(borderRight);
+                borderRight = null;
+                HSLFTableCell c = getSiblingCell(0,1);
+                if (c != null) {
+                    c.borderLeft = null;
+                }
+                break;
+            }
+            case left: {
+                if (borderLeft == null) break;
+                getParent().removeShape(borderLeft);
+                borderLeft = null;
+                HSLFTableCell c = getSiblingCell(0,-1);
+                if (c != null) {
+                    c.borderRight = null;
+                }
+                break;
+            }
+            default:
+                throw new IllegalArgumentException();
+        }
     }
 
-    public HSLFLine getBorderBottom() {
-        return borderBottom;
+    protected HSLFTableCell getSiblingCell(int row, int col) {
+        return getParent().getRelativeCell(this, row, col);
     }
 
-    public void setBorderBottom(HSLFLine line) {
-        if(line != null) anchorBorder(HSLFTable.BORDER_BOTTOM, line);
-        this.borderBottom = line;
+    /**
+     * Create a border to format this table
+     *
+     * @return the created border
+     */
+    private HSLFLine createBorder(BorderEdge edge) {
+        HSLFTable table = getParent();
+        HSLFLine line = new HSLFLine(table);
+        table.addShape(line);
+
+        AbstractEscherOptRecord opt = getEscherOptRecord();
+        setEscherProperty(opt, EscherProperties.GEOMETRY__SHAPEPATH, -1);
+        setEscherProperty(opt, EscherProperties.GEOMETRY__FILLOK, -1);
+        setEscherProperty(opt, EscherProperties.SHADOWSTYLE__SHADOWOBSURED, 0x20000);
+        setEscherProperty(opt, EscherProperties.THREED__LIGHTFACE, 0x80000);
+
+        anchorBorder(edge, line);
+        
+        return line;
     }
 
-    public void setAnchor(Rectangle anchor){
-        super.setAnchor(anchor);
+    protected void applyLineProperties(BorderEdge edge, HSLFLine other) {
+        HSLFLine line = addLine(edge);
+        line.setLineWidth(other.getLineWidth());
+        line.setLineColor(other.getLineColor());
+        // line.setLineCompound(other.getLineCompound());
+        // line.setLineDashing(other.getLineDashing());
+    }
 
-        if(borderTop != null) anchorBorder(HSLFTable.BORDER_TOP, borderTop);
-        if(borderRight != null) anchorBorder(HSLFTable.BORDER_RIGHT, borderRight);
-        if(borderBottom != null) anchorBorder(HSLFTable.BORDER_BOTTOM, borderBottom);
-        if(borderLeft != null) anchorBorder(HSLFTable.BORDER_LEFT, borderLeft);
+    @Override
+    public HSLFTable getParent() {
+        return (HSLFTable)super.getParent();
     }
 }

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java?rev=1711171&r1=1711170&r2=1711171&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java Thu Oct 29 01:05:27 2015
@@ -69,7 +69,7 @@ import org.apache.poi.util.Units;
  * This class represents a run of text in a powerpoint document. That
  *  run could be text on a sheet, or text in a note.
  *  It is only a very basic class for now
- * 
+ *
  * @author Nick Burch
  */
 
@@ -98,18 +98,18 @@ public final class HSLFTextParagraph imp
     private int shapeId;
 
     private StyleTextProp9Atom styleTextProp9Atom;
-    
+
     private boolean _dirty = false;
 
     /**
     * Constructs a Text Run from a Unicode text block.
     * Either a {@link TextCharsAtom} or a {@link TextBytesAtom} needs to be provided.
-     * 
+     *
     * @param tha the TextHeaderAtom that defines what's what
     * @param tba the TextBytesAtom containing the text or null if {@link TextCharsAtom} is provided
     * @param tca the TextCharsAtom containing the text or null if {@link TextBytesAtom} is provided
      */
-	/* package */ HSLFTextParagraph(
+    /* package */ HSLFTextParagraph(
         TextHeaderAtom tha,
         TextBytesAtom tba,
         TextCharsAtom tca
@@ -137,10 +137,7 @@ public final class HSLFTextParagraph imp
         _runs.add(run);
     }
 
-    /**
-	 * Fetch the rich text runs (runs of text with the same styling) that
-	 *  are contained within this block of text
-     */
+    @Override
     public List<HSLFTextRun> getTextRuns() {
         return _runs;
     }
@@ -193,7 +190,7 @@ public final class HSLFTextParagraph imp
 
     /**
      * Sets the index of the paragraph in the SLWT container
-     * 
+     *
      * @param index
      */
     protected void setIndex(int index) {
@@ -241,7 +238,7 @@ public final class HSLFTextParagraph imp
     /**
      * Returns records that make up the list of text paragraphs
      * (there can be misc InteractiveInfo, TxInteractiveInfo and other records)
-     * 
+     *
      * @return text run records
      */
     public Record[] getRecords() {
@@ -278,7 +275,7 @@ public final class HSLFTextParagraph imp
     }
 
     /** Numbered List info */
-	public void setStyleTextProp9Atom(final StyleTextProp9Atom styleTextProp9Atom) {
+    public void setStyleTextProp9Atom(final StyleTextProp9Atom styleTextProp9Atom) {
         this.styleTextProp9Atom = styleTextProp9Atom;
     }
 
@@ -286,7 +283,7 @@ public final class HSLFTextParagraph imp
     public StyleTextProp9Atom getStyleTextProp9Atom() {
         return this.styleTextProp9Atom;
     }
-    
+
     @Override
     public Iterator<HSLFTextRun> iterator() {
         return _runs.iterator();
@@ -342,13 +339,13 @@ public final class HSLFTextParagraph imp
         if (!_runs.isEmpty()) {
             d = _runs.get(0).getFontSize();
         }
-        
+
         return (d != null) ? d : 12d;
     }
 
     /**
      * Sets the type of horizontal alignment for the paragraph.
-     * 
+     *
      * @param align - the type of alignment
      */
     public void setAlignment(org.apache.poi.sl.usermodel.TextParagraph.TextAlign align) {
@@ -386,7 +383,7 @@ public final class HSLFTextParagraph imp
     public FontAlign getFontAlign() {
         TextProp tp = getPropVal(_paragraphStyle, FontAlignmentProp.NAME, this);
         if (tp == null) return null;
-        
+
         switch (tp.getValue()) {
             case FontAlignmentProp.BASELINE: return FontAlign.BASELINE;
             case FontAlignmentProp.TOP: return FontAlign.TOP;
@@ -413,8 +410,8 @@ public final class HSLFTextParagraph imp
         assert(startAt != null);
         return startAt.intValue();
     }
-    
-    
+
+
     @Override
     public BulletStyle getBulletStyle() {
         if (!isBullet() && getAutoNumberingScheme() == null) return null;
@@ -440,7 +437,7 @@ public final class HSLFTextParagraph imp
             public void setBulletFontColor(Color color) {
                 setBulletFontColor(DrawPaint.createSolidPaint(color));
             }
-            
+
             @Override
             public void setBulletFontColor(PaintStyle color) {
                 if (!(color instanceof SolidPaint)) {
@@ -450,7 +447,7 @@ public final class HSLFTextParagraph imp
                 Color col = DrawPaint.applyColorTransform(sp.getSolidColor());
                 HSLFTextParagraph.this.setBulletColor(col);
             }
-            
+
             @Override
             public PaintStyle getBulletFontColor() {
                 Color col = HSLFTextParagraph.this.getBulletColor();
@@ -617,7 +614,7 @@ public final class HSLFTextParagraph imp
         // TODO: implement
         return null;
     }
-    
+
     private Double getPctOrPoints(String propName) {
         TextProp tp = getPropVal(_paragraphStyle, propName, this);
         if (tp == null) return null;
@@ -632,7 +629,7 @@ public final class HSLFTextParagraph imp
         }
         setParagraphTextPropVal(propName, ival);
     }
-    
+
     private boolean getFlag(int index) {
         BitMaskTextProp tp = (BitMaskTextProp)getPropVal(_paragraphStyle, ParagraphFlagsTextProp.NAME, this);
         return (tp == null) ? false : tp.getSubValue(index);
@@ -672,7 +669,7 @@ public final class HSLFTextParagraph imp
     /**
      * Returns the named TextProp, either by fetching it (if it exists) or
      * adding it (if it didn't)
-     * 
+     *
      * @param props the TextPropCollection to fetch from / add into
      * @param name the name of the TextProp to fetch/add
      * @param val the value, null if unset
@@ -682,15 +679,15 @@ public final class HSLFTextParagraph imp
             props.removeByName(name);
             return;
         }
-        
+
         // Fetch / Add the TextProp
         TextProp tp = props.addWithName(name);
         tp.setValue(val);
     }
-    
+
     /**
      * Check and add linebreaks to text runs leading other paragraphs
-     * 
+     *
      * @param paragraphs
      */
     protected static void fixLineEndings(List<HSLFTextParagraph> paragraphs) {
@@ -710,7 +707,7 @@ public final class HSLFTextParagraph imp
 
     /**
      * Search for a StyleTextPropAtom is for this text header (list of paragraphs)
-     * 
+     *
      * @param header the header
      * @param textLen the length of the rawtext, or -1 if the length is not known
      */
@@ -868,7 +865,7 @@ public final class HSLFTextParagraph imp
                 throw new RuntimeException("failed dummy write", e);
             }
         }
-        
+
         for (HSLFTextParagraph p : paragraphs) {
             p._dirty = false;
         }
@@ -877,7 +874,7 @@ public final class HSLFTextParagraph imp
     /**
      * Adds the supplied text onto the end of the TextParagraphs,
      * creating a new RichTextRun for it to sit in.
-     * 
+     *
      * @param text the text string used by this object.
      */
     protected static HSLFTextRun appendText(List<HSLFTextParagraph> paragraphs, String text, boolean newParagraph) {
@@ -889,9 +886,13 @@ public final class HSLFTextParagraph imp
         HSLFTextParagraph htp = paragraphs.get(paragraphs.size() - 1);
         HSLFTextRun htr = htp.getTextRuns().get(htp.getTextRuns().size() - 1);
 
-        boolean isFirst = !newParagraph;
+        boolean addParagraph = newParagraph;
         for (String rawText : text.split("(?<=\r)")) {
-            if (!isFirst) {
+            // special case, if last text paragraph or run is empty, we will reuse it
+            boolean lastRunEmpty = (htr.getLength() == 0);
+            boolean lastParaEmpty = lastRunEmpty && (htp.getTextRuns().size() == 1);
+
+            if (addParagraph && !lastParaEmpty) {
                 TextPropCollection tpc = htp.getParagraphStyle();
                 HSLFTextParagraph prevHtp = htp;
                 htp = new HSLFTextParagraph(htp._headerAtom, htp._byteAtom, htp._charAtom);
@@ -901,11 +902,10 @@ public final class HSLFTextParagraph imp
                 htp.supplySheet(prevHtp.getSheet());
                 paragraphs.add(htp);
             }
-            isFirst = false;
+            addParagraph = true;
 
-            TextPropCollection tpc = htr.getCharacterStyle();
-            // special case, last text run is empty, we will reuse it
-            if (htr.getLength() > 0) {
+            if (!lastRunEmpty) {
+                TextPropCollection tpc = htr.getCharacterStyle();
                 htr = new HSLFTextRun(htp);
                 htr.getCharacterStyle().copy(tpc);
                 htp.addTextRun(htr);
@@ -921,7 +921,7 @@ public final class HSLFTextParagraph imp
     /**
      * Sets (overwrites) the current text.
      * Uses the properties of the first paragraph / textrun
-     * 
+     *
      * @param text the text string used by this object.
      */
     public static HSLFTextRun setText(List<HSLFTextParagraph> paragraphs, String text) {
@@ -980,7 +980,7 @@ public final class HSLFTextParagraph imp
     /**
      * Converts raw text from the text paragraphs to a formatted string,
      * i.e. it converts certain control characters used in the raw txt
-     * 
+     *
      * @param rawText the raw text
      * @param runType the run type of the shape, paragraph or headerAtom.
      *        use -1 if unknown
@@ -1024,7 +1024,7 @@ public final class HSLFTextParagraph imp
      * Scans through the supplied record array, looking for
      * a TextHeaderAtom followed by one of a TextBytesAtom or
      * a TextCharsAtom. Builds up TextRuns from these
-     * 
+     *
      * @param wrapper an EscherTextboxWrapper
      */
     protected static List<HSLFTextParagraph> findTextParagraphs(EscherTextboxWrapper wrapper, HSLFSheet sheet) {
@@ -1103,7 +1103,7 @@ public final class HSLFTextParagraph imp
      * Scans through the supplied record array, looking for
      * a TextHeaderAtom followed by one of a TextBytesAtom or
      * a TextCharsAtom. Builds up TextRuns from these
-     * 
+     *
      * @param records the records to build from
      */
     protected static List<List<HSLFTextParagraph>> findTextParagraphs(Record[] records) {
@@ -1272,7 +1272,7 @@ public final class HSLFTextParagraph imp
         EscherTextboxWrapper wrapper = new EscherTextboxWrapper();
         return createEmptyParagraph(wrapper);
     }
-    
+
     protected static List<HSLFTextParagraph> createEmptyParagraph(EscherTextboxWrapper wrapper) {
         TextHeaderAtom tha = new TextHeaderAtom();
         tha.setParentRecord(wrapper);
@@ -1301,10 +1301,10 @@ public final class HSLFTextParagraph imp
     public EscherTextboxWrapper getTextboxWrapper() {
         return (EscherTextboxWrapper) _headerAtom.getParentRecord();
     }
-    
+
     protected static Color getColorFromColorIndexStruct(int rgb, HSLFSheet sheet) {
         int cidx = rgb >>> 24;
-        Color tmp; 
+        Color tmp;
         switch (cidx) {
             // Background ... Accent 3 color
             case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
@@ -1333,15 +1333,15 @@ public final class HSLFTextParagraph imp
         setPropVal(_paragraphStyle, propName, val);
         setDirty();
     }
-    
+
     /**
      * marks this paragraph dirty, so its records will be renewed on save
      */
     public void setDirty() {
         _dirty = true;
     }
-    
+
     public boolean isDirty() {
         return _dirty;
     }
-}
+}
\ No newline at end of file

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java?rev=1711171&r1=1711170&r2=1711171&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java Thu Oct 29 01:05:27 2015
@@ -157,44 +157,32 @@ public final class HSLFTextRun implement
 
 	// --------------- Friendly getters / setters on rich text properties -------
 
-	/**
-	 * Is the text bold?
-	 */
+	@Override
 	public boolean isBold() {
 		return isCharFlagsTextPropVal(CharFlagsTextProp.BOLD_IDX);
 	}
 
-	/**
-	 * Is the text bold?
-	 */
+	@Override
 	public void setBold(boolean bold) {
 		setCharFlagsTextPropVal(CharFlagsTextProp.BOLD_IDX, bold);
 	}
 
-	/**
-	 * Is the text italic?
-	 */
+	@Override
 	public boolean isItalic() {
 		return isCharFlagsTextPropVal(CharFlagsTextProp.ITALIC_IDX);
 	}
 
-	/**
-	 * Is the text italic?
-	 */
+	@Override
 	public void setItalic(boolean italic) {
 		setCharFlagsTextPropVal(CharFlagsTextProp.ITALIC_IDX, italic);
 	}
 
-	/**
-	 * Is the text underlined?
-	 */
+	@Override
 	public boolean isUnderlined() {
 		return isCharFlagsTextPropVal(CharFlagsTextProp.UNDERLINE_IDX);
 	}
 
-	/**
-	 * Is the text underlined?
-	 */
+	@Override
 	public void setUnderlined(boolean underlined) {
 		setCharFlagsTextPropVal(CharFlagsTextProp.UNDERLINE_IDX, underlined);
 	}
@@ -227,16 +215,12 @@ public final class HSLFTextRun implement
 		setCharFlagsTextPropVal(CharFlagsTextProp.RELIEF_IDX, flag);
 	}
 
-	/**
-	 * Gets the strikethrough flag
-	 */
+	@Override
 	public boolean isStrikethrough() {
 		return isCharFlagsTextPropVal(CharFlagsTextProp.STRIKETHROUGH_IDX);
 	}
 
-	/**
-	 * Sets the strikethrough flag
-	 */
+	@Override
 	public void setStrikethrough(boolean flag) {
 		setCharFlagsTextPropVal(CharFlagsTextProp.STRIKETHROUGH_IDX, flag);
 	}
@@ -288,10 +272,7 @@ public final class HSLFTextRun implement
 		setCharTextPropVal("font.index", idx);
 	}
 
-
-	/**
-	 * Sets the font name to use
-	 */
+	@Override
 	public void setFontFamily(String fontFamily) {
 	    HSLFSheet sheet = parentParagraph.getSheet();
 	    HSLFSlideShow slideShow = (sheet == null) ? null : sheet.getSlideShow();
@@ -301,13 +282,10 @@ public final class HSLFTextRun implement
 			return;
 		}
 		// Get the index for this font (adding if needed)
-		int fontIdx = slideShow.getFontCollection().addFont(fontFamily);
+		Integer fontIdx = (fontFamily == null) ? null : slideShow.getFontCollection().addFont(fontFamily);
 		setCharTextPropVal("font.index", fontIdx);
 	}
 
-	/**
-	 * Gets the font name
-	 */
 	@Override
 	public String getFontFamily() {
         HSLFSheet sheet = parentParagraph.getSheet();
@@ -373,12 +351,14 @@ public final class HSLFTextRun implement
         return TextCap.NONE;
     }
 
+    @Override
     public boolean isSubscript() {
-        return false;
+        return getSuperscript() < 0;
     }
 
+    @Override
     public boolean isSuperscript() {
-        return false;
+        return getSuperscript() > 0;
     }
 
     public byte getPitchAndFamily() {

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextShape.java?rev=1711171&r1=1711170&r2=1711171&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextShape.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextShape.java Thu Oct 29 01:05:27 2015
@@ -17,20 +17,37 @@
 
 package org.apache.poi.hslf.usermodel;
 
-import static org.apache.poi.hslf.record.RecordTypes.*;
+import static org.apache.poi.hslf.record.RecordTypes.OEPlaceholderAtom;
+import static org.apache.poi.hslf.record.RecordTypes.RoundTripHFPlaceholder12;
 
 import java.awt.Rectangle;
 import java.awt.font.FontRenderContext;
 import java.awt.geom.Rectangle2D;
 import java.io.IOException;
-import java.util.*;
-
-import org.apache.poi.ddf.*;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.poi.ddf.AbstractEscherOptRecord;
+import org.apache.poi.ddf.EscherContainerRecord;
+import org.apache.poi.ddf.EscherProperties;
+import org.apache.poi.ddf.EscherSimpleProperty;
+import org.apache.poi.ddf.EscherTextboxRecord;
 import org.apache.poi.hslf.exceptions.HSLFException;
-import org.apache.poi.hslf.record.*;
+import org.apache.poi.hslf.record.EscherTextboxWrapper;
+import org.apache.poi.hslf.record.InteractiveInfo;
+import org.apache.poi.hslf.record.InteractiveInfoAtom;
+import org.apache.poi.hslf.record.OEPlaceholderAtom;
+import org.apache.poi.hslf.record.PPDrawing;
+import org.apache.poi.hslf.record.RoundTripHFPlaceholder12;
+import org.apache.poi.hslf.record.TextHeaderAtom;
+import org.apache.poi.hslf.record.TxInteractiveInfoAtom;
 import org.apache.poi.sl.draw.DrawFactory;
 import org.apache.poi.sl.draw.DrawTextShape;
-import org.apache.poi.sl.usermodel.*;
+import org.apache.poi.sl.usermodel.Insets2D;
+import org.apache.poi.sl.usermodel.ShapeContainer;
+import org.apache.poi.sl.usermodel.TextShape;
+import org.apache.poi.sl.usermodel.VerticalAlignment;
 import org.apache.poi.util.POILogger;
 import org.apache.poi.util.Units;
 
@@ -57,14 +74,35 @@ implements TextShape<HSLFShape,HSLFTextP
     /* package */ static final int AnchorBottomCenteredBaseline = 9;
 
     /**
-     * How to wrap the text
+     * Specifies that a line of text will continue on subsequent lines instead
+     * of extending into or beyond a margin.
+     * Office Excel 2007, Excel 2010, PowerPoint 97, and PowerPoint 2010 read
+     * and use this value properly but do not write it.
      */
     public static final int WrapSquare = 0;
+    /**
+     * Specifies a wrapping rule that is equivalent to that of WrapSquare
+     * Excel 97, Excel 2000, Excel 2002, and Office Excel 2003 use this value.
+     * All other product versions listed at the beginning of this appendix ignore this value.
+     */
     public static final int WrapByPoints = 1;
+    /**
+     * Specifies that a line of text will extend into or beyond a margin instead
+     * of continuing on subsequent lines.
+     * Excel 97, Word 97, Excel 2000, Word 2000, Excel 2002,
+     * and Office Excel 2003 do not use this value.
+     */
     public static final int WrapNone = 2;
+    /**
+     * Specifies a wrapping rule that is undefined and MUST be ignored.
+     */
     public static final int WrapTopBottom = 3;
+    /**
+     * Specifies a wrapping rule that is undefined and MUST be ignored.
+     */
     public static final int WrapThrough = 4;
 
+    
     /**
      * TextRun object which holds actual text and format data
      */
@@ -302,24 +340,6 @@ implements TextShape<HSLFShape,HSLFTextP
         setEscherProperty(EscherProperties.TEXT__ANCHORTEXT, align2);
     }
     
-    @Override
-    public VerticalAlignment getVerticalAlignment() {
-        int va = getAlignment();
-        switch (va) {
-        case AnchorTop:
-        case AnchorTopCentered:
-        case AnchorTopBaseline:
-        case AnchorTopCenteredBaseline: return VerticalAlignment.TOP;
-        case AnchorBottom:
-        case AnchorBottomCentered:
-        case AnchorBottomBaseline:
-        case AnchorBottomCenteredBaseline: return VerticalAlignment.BOTTOM;
-        default:
-        case AnchorMiddle:
-        case AnchorMiddleCentered: return VerticalAlignment.MIDDLE;
-        }
-    }
-
     /**
      * @return true, if vertical alignment is relative to baseline
      * this is only used for older versions less equals Office 2003 
@@ -353,21 +373,33 @@ implements TextShape<HSLFShape,HSLFTextP
             return false;
         }
     }
+
+    @Override
+    public void setHorizontalCentered(Boolean isCentered) {
+        setAlignment(isCentered, getVerticalAlignment());
+    }
     
-    public void setVerticalAlignment(VerticalAlignment vAlign) {
-        setAlignment(isHorizontalCentered(), vAlign);
+    @Override
+    public VerticalAlignment getVerticalAlignment() {
+        int va = getAlignment();
+        switch (va) {
+        case AnchorTop:
+        case AnchorTopCentered:
+        case AnchorTopBaseline:
+        case AnchorTopCenteredBaseline: return VerticalAlignment.TOP;
+        case AnchorBottom:
+        case AnchorBottomCentered:
+        case AnchorBottomBaseline:
+        case AnchorBottomCenteredBaseline: return VerticalAlignment.BOTTOM;
+        default:
+        case AnchorMiddle:
+        case AnchorMiddleCentered: return VerticalAlignment.MIDDLE;
+        }
     }
 
-    /**
-     * Sets if the paragraphs are horizontal centered
-     *
-     * @param isCentered true, if the paragraphs are horizontal centered
-     * A {@code null} values unsets this property.
-     * 
-     * @see TextShape#isHorizontalCentered()
-     */
-    public void setHorizontalCentered(Boolean isCentered){
-        setAlignment(isCentered, getVerticalAlignment());
+    @Override
+    public void setVerticalAlignment(VerticalAlignment vAlign) {
+        setAlignment(isHorizontalCentered(), vAlign);
     }
 
     /**
@@ -479,12 +511,6 @@ implements TextShape<HSLFShape,HSLFTextP
         setEscherProperty(propId, Units.toEMU(margin));
     }    
     
-    @Override
-    public boolean getWordWrap(){
-        int ww = getWordWrapEx();
-        return (ww != WrapNone);
-    }
-
     /**
      * Returns the value indicating word wrap.
      *
@@ -498,17 +524,28 @@ implements TextShape<HSLFShape,HSLFTextP
         EscherSimpleProperty prop = 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){
+    public void setWordWrapEx(int wrap){
         setEscherProperty(EscherProperties.TEXT__WRAPTEXT, wrap);
     }
 
+    @Override
+    public boolean getWordWrap(){
+        int ww = getWordWrapEx();
+        return (ww != WrapNone);
+    }
+
+    @Override
+    public void setWordWrap(boolean wrap) {
+        setWordWrapEx(wrap ? WrapSquare : WrapNone);
+    }
+    
     /**
      * @return id for the text.
      */
@@ -700,6 +737,14 @@ implements TextShape<HSLFShape,HSLFTextP
     }
 
     @Override
+    public void setInsets(Insets2D insets) {
+        setTopInset(insets.top);
+        setLeftInset(insets.left);
+        setBottomInset(insets.bottom);
+        setRightInset(insets.right);
+    }
+
+    @Override
     public double getTextHeight(){
         DrawFactory drawFact = DrawFactory.getInstance(null);
         DrawTextShape dts = drawFact.getDrawable(this);
@@ -747,14 +792,7 @@ implements TextShape<HSLFShape,HSLFTextP
           return HSLFTextParagraph.appendText(paras, text, newParagraph);
       }
 
-      /**
-       * Sets (overwrites) the current text.
-       * Uses the properties of the first paragraph / textrun
-       * 
-       * @param text the text string used by this object.
-       * 
-       * @return the last text run of the splitted text
-       */
+      @Override
       public HSLFTextRun setText(String text) {
           // init paragraphs
           List<HSLFTextParagraph> paras = getTextParagraphs();
@@ -783,5 +821,64 @@ implements TextShape<HSLFShape,HSLFTextP
         return HSLFHyperlink.find(this);
     }
 
+    @Override
+    public void setTextPlaceholder(TextPlaceholder placeholder) {
+        // TOOD: check for correct placeholder handling - see org.apache.poi.hslf.model.Placeholder
+        Placeholder ph = null;
+        int runType;
+        switch (placeholder) {
+            default:
+            case BODY:
+                runType = TextHeaderAtom.BODY_TYPE;
+                ph = Placeholder.BODY;
+                break;
+            case TITLE:
+                runType = TextHeaderAtom.TITLE_TYPE;
+                ph = Placeholder.TITLE;
+                break;
+            case CENTER_BODY:
+                runType = TextHeaderAtom.CENTRE_BODY_TYPE;
+                ph = Placeholder.BODY;
+                break;
+            case CENTER_TITLE:
+                runType = TextHeaderAtom.CENTER_TITLE_TYPE;
+                ph = Placeholder.TITLE;
+                break;
+            case HALF_BODY:
+                runType = TextHeaderAtom.HALF_BODY_TYPE;
+                ph = Placeholder.BODY;
+                break;
+            case QUARTER_BODY:
+                runType = TextHeaderAtom.QUARTER_BODY_TYPE;
+                ph = Placeholder.BODY;
+                break;
+            case NOTES:
+                runType = TextHeaderAtom.NOTES_TYPE;
+                break;
+            case OTHER:
+                runType = TextHeaderAtom.OTHER_TYPE;
+                break;
+        }
+        setRunType(runType);
+        if (ph != null) {
+            setPlaceholder(ph);
+        }
+    }
 
+    @Override
+    public TextPlaceholder getTextPlaceholder() {
+        switch (getRunType()) {
+            default:
+            case TextHeaderAtom.BODY_TYPE: return TextPlaceholder.BODY;
+            case TextHeaderAtom.TITLE_TYPE: return TextPlaceholder.TITLE;
+            case TextHeaderAtom.NOTES_TYPE: return TextPlaceholder.NOTES;
+            case TextHeaderAtom.OTHER_TYPE: return TextPlaceholder.OTHER;
+            case TextHeaderAtom.CENTRE_BODY_TYPE: return TextPlaceholder.CENTER_BODY;
+            case TextHeaderAtom.CENTER_TITLE_TYPE: return TextPlaceholder.CENTER_TITLE;
+            case TextHeaderAtom.HALF_BODY_TYPE: return TextPlaceholder.HALF_BODY;
+            case TextHeaderAtom.QUARTER_BODY_TYPE: return TextPlaceholder.QUARTER_BODY;
+        }
+    }
+
+    
 }
\ No newline at end of file

Modified: poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestLine.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestLine.java?rev=1711171&r1=1711170&r2=1711171&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestLine.java (original)
+++ poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestLine.java Thu Oct 29 01:05:27 2015
@@ -81,27 +81,27 @@ public final class TestLine {
          */
         line = new HSLFLine();
         line.setAnchor(new java.awt.Rectangle(450, 200, 300, 0));
-        line.setLineDashing(LineDash.SOLID);
+        line.setLineDash(LineDash.SOLID);
         slide.addShape(line);
 
         line = new HSLFLine();
         line.setAnchor(new java.awt.Rectangle(450, 230, 300, 0));
-        line.setLineDashing(LineDash.DASH);
+        line.setLineDash(LineDash.DASH);
         slide.addShape(line);
 
         line = new HSLFLine();
         line.setAnchor(new java.awt.Rectangle(450, 260, 300, 0));
-        line.setLineDashing(LineDash.DOT);
+        line.setLineDash(LineDash.DOT);
         slide.addShape(line);
 
         line = new HSLFLine();
         line.setAnchor(new java.awt.Rectangle(450, 290, 300, 0));
-        line.setLineDashing(LineDash.DASH_DOT);
+        line.setLineDash(LineDash.DASH_DOT);
         slide.addShape(line);
 
         line = new HSLFLine();
         line.setAnchor(new java.awt.Rectangle(450, 320, 300, 0));
-        line.setLineDashing(LineDash.LG_DASH_DOT_DOT);
+        line.setLineDash(LineDash.LG_DASH_DOT_DOT);
         slide.addShape(line);
 
         /**
@@ -109,21 +109,21 @@ public final class TestLine {
          */
         line = new HSLFLine();
         line.setAnchor(new java.awt.Rectangle(75, 400, 300, 0));
-        line.setLineDashing(LineDash.DASH_DOT);
+        line.setLineDash(LineDash.DASH_DOT);
         line.setLineCompound(LineCompound.TRIPLE);
         line.setLineWidth(5.0);
         slide.addShape(line);
 
         line = new HSLFLine();
         line.setAnchor(new java.awt.Rectangle(75, 430, 300, 0));
-        line.setLineDashing(LineDash.DASH);
+        line.setLineDash(LineDash.DASH);
         line.setLineCompound(LineCompound.THICK_THIN);
         line.setLineWidth(4.0);
         slide.addShape(line);
 
         line = new HSLFLine();
         line.setAnchor(new java.awt.Rectangle(75, 460, 300, 0));
-        line.setLineDashing(LineDash.DOT);
+        line.setLineDash(LineDash.DOT);
         line.setLineCompound(LineCompound.DOUBLE);
         line.setLineWidth(8.0);
         slide.addShape(line);




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