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: [email protected] For additional commands, e-mail: [email protected]
