#57766 - XSLFTable isn't exported on convert slides of a .pptx slide show to a PNG/SVG image
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1746856 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
1caa8ff288
commit
d80170f9ac
@ -56,6 +56,14 @@ public class DrawFactory {
|
|||||||
defaultFactory.set(factory);
|
defaultFactory.set(factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the DrawFactory, preferably via a graphics instance.
|
||||||
|
* If graphics is null, the current thread local is checked or
|
||||||
|
* if it is not set, a new factory is created.
|
||||||
|
*
|
||||||
|
* @param graphics the current graphics context or null
|
||||||
|
* @return the draw factory
|
||||||
|
*/
|
||||||
public static DrawFactory getInstance(Graphics2D graphics) {
|
public static DrawFactory getInstance(Graphics2D graphics) {
|
||||||
// first try to find the factory over the rendering hint
|
// first try to find the factory over the rendering hint
|
||||||
DrawFactory factory = null;
|
DrawFactory factory = null;
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package org.apache.poi.sl.draw;
|
package org.apache.poi.sl.draw;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.AffineTransform;
|
import java.awt.geom.AffineTransform;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
@ -24,6 +25,9 @@ import java.util.Locale;
|
|||||||
|
|
||||||
import org.apache.poi.sl.usermodel.PlaceableShape;
|
import org.apache.poi.sl.usermodel.PlaceableShape;
|
||||||
import org.apache.poi.sl.usermodel.Shape;
|
import org.apache.poi.sl.usermodel.Shape;
|
||||||
|
import org.apache.poi.sl.usermodel.StrokeStyle;
|
||||||
|
import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;
|
||||||
|
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
|
||||||
|
|
||||||
|
|
||||||
public class DrawShape implements Drawable {
|
public class DrawShape implements Drawable {
|
||||||
@ -157,4 +161,44 @@ public class DrawShape implements Drawable {
|
|||||||
protected Shape<?,?> getShape() {
|
protected Shape<?,?> getShape() {
|
||||||
return shape;
|
return shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static BasicStroke getStroke(StrokeStyle strokeStyle) {
|
||||||
|
float lineWidth = (float) strokeStyle.getLineWidth();
|
||||||
|
if (lineWidth == 0.0f) lineWidth = 0.25f; // Both PowerPoint and OOo draw zero-length lines as 0.25pt
|
||||||
|
|
||||||
|
LineDash lineDash = strokeStyle.getLineDash();
|
||||||
|
if (lineDash == null) {
|
||||||
|
lineDash = LineDash.SOLID;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dashPatI[] = lineDash.pattern;
|
||||||
|
final float dash_phase = 0;
|
||||||
|
float[] dashPatF = null;
|
||||||
|
if (dashPatI != null) {
|
||||||
|
dashPatF = new float[dashPatI.length];
|
||||||
|
for (int i=0; i<dashPatI.length; i++) {
|
||||||
|
dashPatF[i] = dashPatI[i]*Math.max(1, lineWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LineCap lineCapE = strokeStyle.getLineCap();
|
||||||
|
if (lineCapE == null) lineCapE = LineCap.FLAT;
|
||||||
|
int lineCap;
|
||||||
|
switch (lineCapE) {
|
||||||
|
case ROUND:
|
||||||
|
lineCap = BasicStroke.CAP_ROUND;
|
||||||
|
break;
|
||||||
|
case SQUARE:
|
||||||
|
lineCap = BasicStroke.CAP_SQUARE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case FLAT:
|
||||||
|
lineCap = BasicStroke.CAP_BUTT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lineJoin = BasicStroke.JOIN_ROUND;
|
||||||
|
|
||||||
|
return new BasicStroke(lineWidth, lineCap, lineJoin, lineWidth, dashPatF, dash_phase);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,9 +53,6 @@ import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize;
|
|||||||
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
|
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
|
||||||
import org.apache.poi.sl.usermodel.Shadow;
|
import org.apache.poi.sl.usermodel.Shadow;
|
||||||
import org.apache.poi.sl.usermodel.SimpleShape;
|
import org.apache.poi.sl.usermodel.SimpleShape;
|
||||||
import org.apache.poi.sl.usermodel.StrokeStyle;
|
|
||||||
import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;
|
|
||||||
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
|
|
||||||
import org.apache.poi.util.Units;
|
import org.apache.poi.util.Units;
|
||||||
|
|
||||||
|
|
||||||
@ -282,45 +279,7 @@ public class DrawSimpleShape extends DrawShape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public BasicStroke getStroke() {
|
public BasicStroke getStroke() {
|
||||||
StrokeStyle strokeStyle = getShape().getStrokeStyle();
|
return getStroke(getShape().getStrokeStyle());
|
||||||
|
|
||||||
float lineWidth = (float) strokeStyle.getLineWidth();
|
|
||||||
if (lineWidth == 0.0f) lineWidth = 0.25f; // Both PowerPoint and OOo draw zero-length lines as 0.25pt
|
|
||||||
|
|
||||||
LineDash lineDash = strokeStyle.getLineDash();
|
|
||||||
if (lineDash == null) {
|
|
||||||
lineDash = LineDash.SOLID;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dashPatI[] = lineDash.pattern;
|
|
||||||
final float dash_phase = 0;
|
|
||||||
float[] dashPatF = null;
|
|
||||||
if (dashPatI != null) {
|
|
||||||
dashPatF = new float[dashPatI.length];
|
|
||||||
for (int i=0; i<dashPatI.length; i++) {
|
|
||||||
dashPatF[i] = dashPatI[i]*Math.max(1, lineWidth);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LineCap lineCapE = strokeStyle.getLineCap();
|
|
||||||
if (lineCapE == null) lineCapE = LineCap.FLAT;
|
|
||||||
int lineCap;
|
|
||||||
switch (lineCapE) {
|
|
||||||
case ROUND:
|
|
||||||
lineCap = BasicStroke.CAP_ROUND;
|
|
||||||
break;
|
|
||||||
case SQUARE:
|
|
||||||
lineCap = BasicStroke.CAP_SQUARE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
case FLAT:
|
|
||||||
lineCap = BasicStroke.CAP_BUTT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int lineJoin = BasicStroke.JOIN_ROUND;
|
|
||||||
|
|
||||||
return new BasicStroke(lineWidth, lineCap, lineJoin, lineWidth, dashPatF, dash_phase);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void drawShadow(
|
protected void drawShadow(
|
||||||
|
@ -19,21 +19,31 @@ package org.apache.poi.sl.draw;
|
|||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Paint;
|
||||||
|
import java.awt.geom.Line2D;
|
||||||
|
import java.awt.geom.Rectangle2D;
|
||||||
|
|
||||||
import org.apache.poi.sl.usermodel.GroupShape;
|
import org.apache.poi.sl.usermodel.GroupShape;
|
||||||
|
import org.apache.poi.sl.usermodel.StrokeStyle;
|
||||||
import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;
|
import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;
|
||||||
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
|
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
|
||||||
import org.apache.poi.sl.usermodel.TableCell;
|
import org.apache.poi.sl.usermodel.TableCell;
|
||||||
import org.apache.poi.sl.usermodel.TableCell.BorderEdge;
|
import org.apache.poi.sl.usermodel.TableCell.BorderEdge;
|
||||||
|
import org.apache.poi.util.Internal;
|
||||||
import org.apache.poi.sl.usermodel.TableShape;
|
import org.apache.poi.sl.usermodel.TableShape;
|
||||||
|
|
||||||
public class DrawTableShape extends DrawShape {
|
public class DrawTableShape extends DrawShape {
|
||||||
// to be implemented ...
|
/**
|
||||||
|
* Additional spacing between cells
|
||||||
|
*/
|
||||||
|
@Internal
|
||||||
|
public static final int borderSize = 2;
|
||||||
|
|
||||||
public DrawTableShape(TableShape<?,?> shape) {
|
public DrawTableShape(TableShape<?,?> shape) {
|
||||||
super(shape);
|
super(shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Drawable getDrawable(Graphics2D graphics) {
|
protected Drawable getGroupShape(Graphics2D graphics) {
|
||||||
if (shape instanceof GroupShape) {
|
if (shape instanceof GroupShape) {
|
||||||
DrawFactory df = DrawFactory.getInstance(graphics);
|
DrawFactory df = DrawFactory.getInstance(graphics);
|
||||||
return df.getDrawable((GroupShape<?,?>)shape);
|
return df.getDrawable((GroupShape<?,?>)shape);
|
||||||
@ -42,23 +52,94 @@ public class DrawTableShape extends DrawShape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void applyTransform(Graphics2D graphics) {
|
public void applyTransform(Graphics2D graphics) {
|
||||||
Drawable d = getDrawable(graphics);
|
Drawable d = getGroupShape(graphics);
|
||||||
if (d != null) {
|
if (d != null) {
|
||||||
d.applyTransform(graphics);
|
d.applyTransform(graphics);
|
||||||
|
} else {
|
||||||
|
super.applyTransform(graphics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void draw(Graphics2D graphics) {
|
public void draw(Graphics2D graphics) {
|
||||||
Drawable d = getDrawable(graphics);
|
Drawable d = getGroupShape(graphics);
|
||||||
if (d != null) {
|
if (d != null) {
|
||||||
d.draw(graphics);
|
d.draw(graphics);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TableShape<?,?> ts = getShape();
|
||||||
|
DrawPaint drawPaint = DrawFactory.getInstance(graphics).getPaint(ts);
|
||||||
|
final int rows = ts.getNumberOfRows();
|
||||||
|
final int cols = ts.getNumberOfColumns();
|
||||||
|
|
||||||
|
// draw background boxes
|
||||||
|
for (int row=0; row<rows; row++) {
|
||||||
|
for (int col=0; col<cols; col++) {
|
||||||
|
TableCell<?,?> tc = ts.getCell(row, col);
|
||||||
|
if (tc == null || tc.isMerged()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Paint fillPaint = drawPaint.getPaint(graphics, tc.getFillStyle().getPaint());
|
||||||
|
graphics.setPaint(fillPaint);
|
||||||
|
Rectangle2D cellAnc = tc.getAnchor();
|
||||||
|
graphics.fill(cellAnc);
|
||||||
|
|
||||||
|
for (BorderEdge edge : BorderEdge.values()) {
|
||||||
|
StrokeStyle stroke = tc.getBorderStyle(edge);
|
||||||
|
if (stroke == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
graphics.setStroke(getStroke(stroke));
|
||||||
|
Paint linePaint = drawPaint.getPaint(graphics, stroke.getPaint());
|
||||||
|
graphics.setPaint(linePaint);
|
||||||
|
|
||||||
|
double x=cellAnc.getX(), y=cellAnc.getY(), w=cellAnc.getWidth(), h=cellAnc.getHeight();
|
||||||
|
Line2D line;
|
||||||
|
switch (edge) {
|
||||||
|
default:
|
||||||
|
case bottom:
|
||||||
|
line = new Line2D.Double(x-borderSize, y+h, x+w+borderSize, y+h);
|
||||||
|
break;
|
||||||
|
case left:
|
||||||
|
line = new Line2D.Double(x, y, x, y+h+borderSize);
|
||||||
|
break;
|
||||||
|
case right:
|
||||||
|
line = new Line2D.Double(x+w, y, x+w, y+h+borderSize);
|
||||||
|
break;
|
||||||
|
case top:
|
||||||
|
line = new Line2D.Double(x-borderSize, y, x+w+borderSize, y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
graphics.draw(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw text
|
||||||
|
drawContent(graphics);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawContent(Graphics2D graphics) {
|
public void drawContent(Graphics2D graphics) {
|
||||||
Drawable d = getDrawable(graphics);
|
Drawable d = getGroupShape(graphics);
|
||||||
if (d != null) {
|
if (d != null) {
|
||||||
d.drawContent(graphics);
|
d.drawContent(graphics);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TableShape<?,?> ts = getShape();
|
||||||
|
DrawFactory df = DrawFactory.getInstance(graphics);
|
||||||
|
|
||||||
|
final int rows = ts.getNumberOfRows();
|
||||||
|
final int cols = ts.getNumberOfColumns();
|
||||||
|
|
||||||
|
for (int row=0; row<rows; row++) {
|
||||||
|
for (int col=0; col<cols; col++) {
|
||||||
|
TableCell<?,?> tc = ts.getCell(row, col);
|
||||||
|
DrawTextShape dts = df.getDrawable(tc);
|
||||||
|
dts.drawContent(graphics);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,5 +249,4 @@ public class DrawTableShape extends DrawShape {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package org.apache.poi.sl.draw;
|
package org.apache.poi.sl.draw;
|
||||||
|
|
||||||
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Paint;
|
import java.awt.Paint;
|
||||||
import java.awt.font.FontRenderContext;
|
import java.awt.font.FontRenderContext;
|
||||||
@ -45,9 +46,11 @@ import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
|
|||||||
import org.apache.poi.sl.usermodel.TextRun;
|
import org.apache.poi.sl.usermodel.TextRun;
|
||||||
import org.apache.poi.sl.usermodel.TextRun.TextCap;
|
import org.apache.poi.sl.usermodel.TextRun.TextCap;
|
||||||
import org.apache.poi.sl.usermodel.TextShape;
|
import org.apache.poi.sl.usermodel.TextShape;
|
||||||
|
import org.apache.poi.sl.usermodel.TextShape.TextDirection;
|
||||||
import org.apache.poi.util.StringUtil;
|
import org.apache.poi.util.StringUtil;
|
||||||
import org.apache.poi.util.Units;
|
import org.apache.poi.util.Units;
|
||||||
|
|
||||||
|
|
||||||
public class DrawTextParagraph implements Drawable {
|
public class DrawTextParagraph implements Drawable {
|
||||||
/** Keys for passing hyperlinks to the graphics context */
|
/** Keys for passing hyperlinks to the graphics context */
|
||||||
public static final XlinkAttribute HYPERLINK_HREF = new XlinkAttribute("href");
|
public static final XlinkAttribute HYPERLINK_HREF = new XlinkAttribute("href");
|
||||||
@ -390,14 +393,13 @@ public class DrawTextParagraph implements Drawable {
|
|||||||
* @return wrapping width in points
|
* @return wrapping width in points
|
||||||
*/
|
*/
|
||||||
protected double getWrappingWidth(boolean firstLine, Graphics2D graphics){
|
protected double getWrappingWidth(boolean firstLine, Graphics2D graphics){
|
||||||
// internal margins for the text box
|
TextShape<?,?> ts = paragraph.getParentShape();
|
||||||
|
|
||||||
Insets2D insets = paragraph.getParentShape().getInsets();
|
// internal margins for the text box
|
||||||
|
Insets2D insets = ts.getInsets();
|
||||||
double leftInset = insets.left;
|
double leftInset = insets.left;
|
||||||
double rightInset = insets.right;
|
double rightInset = insets.right;
|
||||||
|
|
||||||
Rectangle2D anchor = DrawShape.getAnchor(graphics, paragraph.getParentShape());
|
|
||||||
|
|
||||||
int indentLevel = paragraph.getIndentLevel();
|
int indentLevel = paragraph.getIndentLevel();
|
||||||
if (indentLevel == -1) {
|
if (indentLevel == -1) {
|
||||||
// default to 0, if indentLevel is not set
|
// default to 0, if indentLevel is not set
|
||||||
@ -417,13 +419,33 @@ public class DrawTextParagraph implements Drawable {
|
|||||||
rightMargin = 0d;
|
rightMargin = 0d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle2D anchor = DrawShape.getAnchor(graphics, ts);
|
||||||
|
TextDirection textDir = ts.getTextDirection();
|
||||||
double width;
|
double width;
|
||||||
TextShape<?,?> ts = paragraph.getParentShape();
|
|
||||||
if (!ts.getWordWrap()) {
|
if (!ts.getWordWrap()) {
|
||||||
// if wordWrap == false then we return the advance to the right border of the sheet
|
Dimension pageDim = ts.getSheet().getSlideShow().getPageSize();
|
||||||
width = ts.getSheet().getSlideShow().getPageSize().getWidth() - anchor.getX();
|
// if wordWrap == false then we return the advance to the (right) border of the sheet
|
||||||
|
switch (textDir) {
|
||||||
|
default:
|
||||||
|
width = pageDim.getWidth() - anchor.getX();
|
||||||
|
break;
|
||||||
|
case VERTICAL:
|
||||||
|
width = pageDim.getHeight() - anchor.getX();
|
||||||
|
break;
|
||||||
|
case VERTICAL_270:
|
||||||
|
width = anchor.getX();
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
width = anchor.getWidth() - leftInset - rightInset - leftMargin - rightMargin;
|
switch (textDir) {
|
||||||
|
default:
|
||||||
|
width = anchor.getWidth() - leftInset - rightInset - leftMargin - rightMargin;
|
||||||
|
break;
|
||||||
|
case VERTICAL:
|
||||||
|
case VERTICAL_270:
|
||||||
|
width = anchor.getHeight() - leftInset - rightInset - leftMargin - rightMargin;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (firstLine && !isHSLF()) {
|
if (firstLine && !isHSLF()) {
|
||||||
if (bullet != null){
|
if (bullet != null){
|
||||||
if (indent > 0) width -= indent;
|
if (indent > 0) width -= indent;
|
||||||
|
@ -30,6 +30,7 @@ import org.apache.poi.sl.usermodel.TextParagraph;
|
|||||||
import org.apache.poi.sl.usermodel.TextParagraph.BulletStyle;
|
import org.apache.poi.sl.usermodel.TextParagraph.BulletStyle;
|
||||||
import org.apache.poi.sl.usermodel.TextRun;
|
import org.apache.poi.sl.usermodel.TextRun;
|
||||||
import org.apache.poi.sl.usermodel.TextShape;
|
import org.apache.poi.sl.usermodel.TextShape;
|
||||||
|
import org.apache.poi.sl.usermodel.TextShape.TextDirection;
|
||||||
|
|
||||||
public class DrawTextShape extends DrawSimpleShape {
|
public class DrawTextShape extends DrawSimpleShape {
|
||||||
|
|
||||||
@ -98,6 +99,20 @@ public class DrawTextShape extends DrawSimpleShape {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextDirection textDir = s.getTextDirection();
|
||||||
|
if (textDir == TextDirection.VERTICAL || textDir == TextDirection.VERTICAL_270) {
|
||||||
|
double deg = (textDir == TextDirection.VERTICAL) ? 90 : 270;
|
||||||
|
graphics.translate(anchor.getCenterX(), anchor.getCenterY());
|
||||||
|
graphics.rotate(Math.toRadians(deg));
|
||||||
|
graphics.translate(-anchor.getCenterX(), -anchor.getCenterY());
|
||||||
|
|
||||||
|
// old top/left edge is now bottom/left or top/right - as we operate on the already
|
||||||
|
// rotated drawing context, both verticals can be moved in the same direction
|
||||||
|
double w = anchor.getWidth();
|
||||||
|
double h = anchor.getHeight();
|
||||||
|
graphics.translate((w-h)/2d,(h-w)/2d);
|
||||||
|
}
|
||||||
|
|
||||||
drawParagraphs(graphics, x, y);
|
drawParagraphs(graphics, x, y);
|
||||||
|
|
||||||
// restore the transform
|
// restore the transform
|
||||||
|
@ -83,4 +83,32 @@ public interface TableCell<
|
|||||||
* @param edge the border edge to be cleared
|
* @param edge the border edge to be cleared
|
||||||
*/
|
*/
|
||||||
void removeBorder(BorderEdge edge);
|
void removeBorder(BorderEdge edge);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of columns to be spanned/merged
|
||||||
|
*
|
||||||
|
* @return the grid span
|
||||||
|
*
|
||||||
|
* @since POI 3.15-beta2
|
||||||
|
*/
|
||||||
|
int getGridSpan();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of rows to be spanned/merged
|
||||||
|
*
|
||||||
|
* @return the row span
|
||||||
|
*
|
||||||
|
* @since POI 3.15-beta2
|
||||||
|
*/
|
||||||
|
int getRowSpan();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return if this cell is part of a merged cell. The top/left cell of a merged region is not regarded as merged -
|
||||||
|
* its grid and/or row span is greater than one.
|
||||||
|
*
|
||||||
|
* @return true if this a merged cell
|
||||||
|
*
|
||||||
|
* @since POI 3.15-beta2
|
||||||
|
*/
|
||||||
|
boolean isMerged();
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ import org.apache.poi.util.POILogFactory;
|
|||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
import org.apache.xmlbeans.XmlObject;
|
import org.apache.xmlbeans.XmlObject;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTColor;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTColor;
|
||||||
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTFontReference;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTHslColor;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTHslColor;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveFixedPercentage;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveFixedPercentage;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetColor;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetColor;
|
||||||
@ -165,6 +166,8 @@ public class XSLFColor {
|
|||||||
color = Color.black;
|
color = Color.black;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (ch instanceof CTFontReference) {
|
||||||
|
// try next ...
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Unexpected color choice: " + ch.getClass());
|
throw new IllegalArgumentException("Unexpected color choice: " + ch.getClass());
|
||||||
}
|
}
|
||||||
|
@ -65,8 +65,6 @@ import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Base super-class class for all shapes in PresentationML
|
* Base super-class class for all shapes in PresentationML
|
||||||
*
|
|
||||||
* @author Yegor Kozlov
|
|
||||||
*/
|
*/
|
||||||
@Beta
|
@Beta
|
||||||
public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
||||||
@ -150,6 +148,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected PaintStyle getFillPaint() {
|
protected PaintStyle getFillPaint() {
|
||||||
|
final XSLFTheme theme = getSheet().getTheme();
|
||||||
PropertyFetcher<PaintStyle> fetcher = new PropertyFetcher<PaintStyle>() {
|
PropertyFetcher<PaintStyle> fetcher = new PropertyFetcher<PaintStyle>() {
|
||||||
public boolean fetch(XSLFShape shape) {
|
public boolean fetch(XSLFShape shape) {
|
||||||
XmlObject pr = null;
|
XmlObject pr = null;
|
||||||
@ -178,7 +177,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||||||
PaintStyle paint = null;
|
PaintStyle paint = null;
|
||||||
PackagePart pp = getSheet().getPackagePart();
|
PackagePart pp = getSheet().getPackagePart();
|
||||||
for (XmlObject obj : pr.selectPath("*")) {
|
for (XmlObject obj : pr.selectPath("*")) {
|
||||||
paint = selectPaint(obj, null, pp);
|
paint = selectPaint(obj, null, pp, theme);
|
||||||
if (paint != null) {
|
if (paint != null) {
|
||||||
setValue(paint);
|
setValue(paint);
|
||||||
return true;
|
return true;
|
||||||
@ -203,7 +202,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||||||
if (fillRef == null) {
|
if (fillRef == null) {
|
||||||
fillRef = getBgRef();
|
fillRef = getBgRef();
|
||||||
}
|
}
|
||||||
paint = selectPaint(fillRef);
|
paint = selectPaint(fillRef, theme);
|
||||||
|
|
||||||
return paint;
|
return paint;
|
||||||
}
|
}
|
||||||
@ -365,9 +364,11 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||||||
|
|
||||||
protected PaintStyle getPaint(XmlObject spPr, CTSchemeColor phClr) {
|
protected PaintStyle getPaint(XmlObject spPr, CTSchemeColor phClr) {
|
||||||
PaintStyle paint = null;
|
PaintStyle paint = null;
|
||||||
PackagePart pp = getSheet().getPackagePart();
|
XSLFSheet sheet = getSheet();
|
||||||
|
PackagePart pp = sheet.getPackagePart();
|
||||||
|
XSLFTheme theme = sheet.getTheme();
|
||||||
for (XmlObject obj : spPr.selectPath("*")) {
|
for (XmlObject obj : spPr.selectPath("*")) {
|
||||||
paint = selectPaint(obj, phClr, pp);
|
paint = selectPaint(obj, phClr, pp, theme);
|
||||||
if(paint != null) break;
|
if(paint != null) break;
|
||||||
}
|
}
|
||||||
return paint;
|
return paint;
|
||||||
@ -392,24 +393,23 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||||||
*
|
*
|
||||||
* @return the applied Paint or null if none was applied
|
* @return the applied Paint or null if none was applied
|
||||||
*/
|
*/
|
||||||
protected PaintStyle selectPaint(XmlObject obj, final CTSchemeColor phClr, final PackagePart parentPart) {
|
protected static PaintStyle selectPaint(XmlObject obj, final CTSchemeColor phClr, final PackagePart parentPart, final XSLFTheme theme) {
|
||||||
if (obj instanceof CTNoFillProperties) {
|
if (obj instanceof CTNoFillProperties) {
|
||||||
return null;
|
return null;
|
||||||
} else if (obj instanceof CTSolidColorFillProperties) {
|
} else if (obj instanceof CTSolidColorFillProperties) {
|
||||||
return selectPaint((CTSolidColorFillProperties)obj, phClr);
|
return selectPaint((CTSolidColorFillProperties)obj, phClr, theme);
|
||||||
} else if (obj instanceof CTBlipFillProperties) {
|
} else if (obj instanceof CTBlipFillProperties) {
|
||||||
return selectPaint((CTBlipFillProperties)obj, parentPart);
|
return selectPaint((CTBlipFillProperties)obj, parentPart);
|
||||||
} else if (obj instanceof CTGradientFillProperties) {
|
} else if (obj instanceof CTGradientFillProperties) {
|
||||||
return selectPaint((CTGradientFillProperties) obj, phClr);
|
return selectPaint((CTGradientFillProperties) obj, phClr, theme);
|
||||||
} else if (obj instanceof CTStyleMatrixReference) {
|
} else if (obj instanceof CTStyleMatrixReference) {
|
||||||
return selectPaint((CTStyleMatrixReference)obj);
|
return selectPaint((CTStyleMatrixReference)obj, theme);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected PaintStyle selectPaint(CTSolidColorFillProperties solidFill, CTSchemeColor phClr) {
|
protected static PaintStyle selectPaint(CTSolidColorFillProperties solidFill, CTSchemeColor phClr, final XSLFTheme theme) {
|
||||||
final XSLFTheme theme = getSheet().getTheme();
|
|
||||||
if (phClr == null && solidFill.isSetSchemeClr()) {
|
if (phClr == null && solidFill.isSetSchemeClr()) {
|
||||||
phClr = solidFill.getSchemeClr();
|
phClr = solidFill.getSchemeClr();
|
||||||
}
|
}
|
||||||
@ -417,7 +417,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||||||
return DrawPaint.createSolidPaint(c.getColorStyle());
|
return DrawPaint.createSolidPaint(c.getColorStyle());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected PaintStyle selectPaint(final CTBlipFillProperties blipFill, final PackagePart parentPart) {
|
protected static PaintStyle selectPaint(final CTBlipFillProperties blipFill, final PackagePart parentPart) {
|
||||||
final CTBlip blip = blipFill.getBlip();
|
final CTBlip blip = blipFill.getBlip();
|
||||||
return new TexturePaint() {
|
return new TexturePaint() {
|
||||||
private PackagePart getPart() {
|
private PackagePart getPart() {
|
||||||
@ -451,7 +451,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected PaintStyle selectPaint(final CTGradientFillProperties gradFill, CTSchemeColor phClr) {
|
protected static PaintStyle selectPaint(final CTGradientFillProperties gradFill, CTSchemeColor phClr, final XSLFTheme theme) {
|
||||||
|
|
||||||
final CTGradientStop[] gs = gradFill.getGsLst().getGsArray();
|
final CTGradientStop[] gs = gradFill.getGsLst().getGsArray();
|
||||||
|
|
||||||
@ -465,7 +465,6 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||||||
|
|
||||||
final ColorStyle cs[] = new ColorStyle[gs.length];
|
final ColorStyle cs[] = new ColorStyle[gs.length];
|
||||||
final float fractions[] = new float[gs.length];
|
final float fractions[] = new float[gs.length];
|
||||||
XSLFTheme theme = getSheet().getTheme();
|
|
||||||
|
|
||||||
int i=0;
|
int i=0;
|
||||||
for (CTGradientStop cgs : gs) {
|
for (CTGradientStop cgs : gs) {
|
||||||
@ -519,7 +518,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected PaintStyle selectPaint(CTStyleMatrixReference fillRef) {
|
protected static PaintStyle selectPaint(CTStyleMatrixReference fillRef, final XSLFTheme theme) {
|
||||||
if (fillRef == null) return null;
|
if (fillRef == null) return null;
|
||||||
|
|
||||||
// The idx attribute refers to the index of a fill style or
|
// The idx attribute refers to the index of a fill style or
|
||||||
@ -529,8 +528,6 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||||||
// values 1001 and above refer to the index of a background fill style within the bgFillStyleLst element.
|
// values 1001 and above refer to the index of a background fill style within the bgFillStyleLst element.
|
||||||
int idx = (int)fillRef.getIdx();
|
int idx = (int)fillRef.getIdx();
|
||||||
CTSchemeColor phClr = fillRef.getSchemeClr();
|
CTSchemeColor phClr = fillRef.getSchemeClr();
|
||||||
XSLFSheet sheet = getSheet();
|
|
||||||
XSLFTheme theme = sheet.getTheme();
|
|
||||||
XmlObject fillProps = null;
|
XmlObject fillProps = null;
|
||||||
CTStyleMatrix matrix = theme.getXmlObject().getThemeElements().getFmtScheme();
|
CTStyleMatrix matrix = theme.getXmlObject().getThemeElements().getFmtScheme();
|
||||||
if (idx >= 1 && idx <= 999) {
|
if (idx >= 1 && idx <= 999) {
|
||||||
@ -538,7 +535,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||||||
} else if (idx >= 1001 ){
|
} else if (idx >= 1001 ){
|
||||||
fillProps = matrix.getBgFillStyleLst().selectPath("*")[idx - 1001];
|
fillProps = matrix.getBgFillStyleLst().selectPath("*")[idx - 1001];
|
||||||
}
|
}
|
||||||
return (fillProps == null) ? null : selectPaint(fillProps, phClr, theme.getPackagePart());
|
return (fillProps == null) ? null : selectPaint(fillProps, phClr, theme.getPackagePart(), theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -77,8 +77,6 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a single (non-group) shape in a .pptx slide show
|
* Represents a single (non-group) shape in a .pptx slide show
|
||||||
*
|
|
||||||
* @author Yegor Kozlov
|
|
||||||
*/
|
*/
|
||||||
@Beta
|
@Beta
|
||||||
public abstract class XSLFSimpleShape extends XSLFShape
|
public abstract class XSLFSimpleShape extends XSLFShape
|
||||||
@ -259,6 +257,7 @@ public abstract class XSLFSimpleShape extends XSLFShape
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected PaintStyle getLinePaint() {
|
protected PaintStyle getLinePaint() {
|
||||||
|
final XSLFTheme theme = getSheet().getTheme();
|
||||||
PropertyFetcher<PaintStyle> fetcher = new PropertyFetcher<PaintStyle>() {
|
PropertyFetcher<PaintStyle> fetcher = new PropertyFetcher<PaintStyle>() {
|
||||||
public boolean fetch(XSLFShape shape) {
|
public boolean fetch(XSLFShape shape) {
|
||||||
CTLineProperties spPr = shape.getSpPr().getLn();
|
CTLineProperties spPr = shape.getSpPr().getLn();
|
||||||
@ -271,7 +270,7 @@ public abstract class XSLFSimpleShape extends XSLFShape
|
|||||||
PaintStyle paint = null;
|
PaintStyle paint = null;
|
||||||
PackagePart pp = getSheet().getPackagePart();
|
PackagePart pp = getSheet().getPackagePart();
|
||||||
for (XmlObject obj : spPr.selectPath("*")) {
|
for (XmlObject obj : spPr.selectPath("*")) {
|
||||||
paint = selectPaint(obj, null, pp);
|
paint = selectPaint(obj, null, pp, theme);
|
||||||
if (paint != null) {
|
if (paint != null) {
|
||||||
setValue(paint);
|
setValue(paint);
|
||||||
return true;
|
return true;
|
||||||
@ -280,7 +279,7 @@ public abstract class XSLFSimpleShape extends XSLFShape
|
|||||||
|
|
||||||
CTShapeStyle style = shape.getSpStyle();
|
CTShapeStyle style = shape.getSpStyle();
|
||||||
if (style != null) {
|
if (style != null) {
|
||||||
paint = selectPaint(style.getLnRef());
|
paint = selectPaint(style.getLnRef(), theme);
|
||||||
if (paint != null) {
|
if (paint != null) {
|
||||||
setValue(paint);
|
setValue(paint);
|
||||||
return true;
|
return true;
|
||||||
@ -305,7 +304,6 @@ public abstract class XSLFSimpleShape extends XSLFShape
|
|||||||
int idx = (int)lnRef.getIdx();
|
int idx = (int)lnRef.getIdx();
|
||||||
CTSchemeColor phClr = lnRef.getSchemeClr();
|
CTSchemeColor phClr = lnRef.getSchemeClr();
|
||||||
if(idx > 0){
|
if(idx > 0){
|
||||||
XSLFTheme theme = getSheet().getTheme();
|
|
||||||
XmlObject lnProps = theme.getXmlObject().
|
XmlObject lnProps = theme.getXmlObject().
|
||||||
getThemeElements().getFmtScheme().getLnStyleLst().selectPath("*")[idx - 1];
|
getThemeElements().getFmtScheme().getLnStyleLst().selectPath("*")[idx - 1];
|
||||||
paint = getPaint(lnProps, phClr);
|
paint = getPaint(lnProps, phClr);
|
||||||
|
@ -21,6 +21,7 @@ package org.apache.poi.xslf.usermodel;
|
|||||||
|
|
||||||
import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
|
import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
|
||||||
|
|
||||||
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -29,6 +30,9 @@ import java.util.List;
|
|||||||
import javax.xml.namespace.QName;
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
import org.apache.poi.POIXMLException;
|
import org.apache.poi.POIXMLException;
|
||||||
|
import org.apache.poi.sl.draw.DrawFactory;
|
||||||
|
import org.apache.poi.sl.draw.DrawTableShape;
|
||||||
|
import org.apache.poi.sl.draw.DrawTextShape;
|
||||||
import org.apache.poi.sl.usermodel.TableShape;
|
import org.apache.poi.sl.usermodel.TableShape;
|
||||||
import org.apache.poi.util.Internal;
|
import org.apache.poi.util.Internal;
|
||||||
import org.apache.poi.util.Units;
|
import org.apache.poi.util.Units;
|
||||||
@ -45,12 +49,10 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFra
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a table in a .pptx presentation
|
* Represents a table in a .pptx presentation
|
||||||
*
|
|
||||||
* @author Yegor Kozlov
|
|
||||||
*/
|
*/
|
||||||
public class XSLFTable extends XSLFGraphicFrame implements Iterable<XSLFTableRow>,
|
public class XSLFTable extends XSLFGraphicFrame implements Iterable<XSLFTableRow>,
|
||||||
TableShape<XSLFShape,XSLFTextParagraph> {
|
TableShape<XSLFShape,XSLFTextParagraph> {
|
||||||
static String TABLE_URI = "http://schemas.openxmlformats.org/drawingml/2006/table";
|
/* package */ static final String TABLE_URI = "http://schemas.openxmlformats.org/drawingml/2006/table";
|
||||||
|
|
||||||
private CTTable _table;
|
private CTTable _table;
|
||||||
private List<XSLFTableRow> _rows;
|
private List<XSLFTableRow> _rows;
|
||||||
@ -77,7 +79,11 @@ public class XSLFTable extends XSLFGraphicFrame implements Iterable<XSLFTableRow
|
|||||||
_table = (CTTable) rs[0];
|
_table = (CTTable) rs[0];
|
||||||
CTTableRow[] trArray = _table.getTrArray();
|
CTTableRow[] trArray = _table.getTrArray();
|
||||||
_rows = new ArrayList<XSLFTableRow>(trArray.length);
|
_rows = new ArrayList<XSLFTableRow>(trArray.length);
|
||||||
for(CTTableRow row : trArray) _rows.add(new XSLFTableRow(row, this));
|
for(CTTableRow row : trArray) {
|
||||||
|
XSLFTableRow xr = new XSLFTableRow(row, this);
|
||||||
|
_rows.add(xr);
|
||||||
|
}
|
||||||
|
updateRowColIndexes();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -146,8 +152,10 @@ public class XSLFTable extends XSLFGraphicFrame implements Iterable<XSLFTableRow
|
|||||||
public XSLFTableRow addRow(){
|
public XSLFTableRow addRow(){
|
||||||
CTTableRow tr = _table.addNewTr();
|
CTTableRow tr = _table.addNewTr();
|
||||||
XSLFTableRow row = new XSLFTableRow(tr, this);
|
XSLFTableRow row = new XSLFTableRow(tr, this);
|
||||||
row.setHeight(20.0); // default height is 20 points
|
// default height is 20 points
|
||||||
|
row.setHeight(20.0);
|
||||||
_rows.add(row);
|
_rows.add(row);
|
||||||
|
updateRowColIndexes();
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,4 +232,110 @@ public class XSLFTable extends XSLFGraphicFrame implements Iterable<XSLFTableRow
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get assigned TableStyle
|
||||||
|
*
|
||||||
|
* @return the assigned TableStyle
|
||||||
|
*
|
||||||
|
* @since POI 3.15-beta2
|
||||||
|
*/
|
||||||
|
protected XSLFTableStyle getTableStyle() {
|
||||||
|
CTTable tab = getCTTable();
|
||||||
|
// TODO: support inline table style
|
||||||
|
if (!tab.isSetTblPr() || !tab.getTblPr().isSetTableStyleId()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String styleId = tab.getTblPr().getTableStyleId();
|
||||||
|
XSLFTableStyles styles = getSheet().getSlideShow().getTableStyles();
|
||||||
|
for (XSLFTableStyle style : styles.getStyles()) {
|
||||||
|
if (style.getStyleId().equals(styleId)) {
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ void updateRowColIndexes() {
|
||||||
|
int rowIdx = 0;
|
||||||
|
for (XSLFTableRow xr : this) {
|
||||||
|
int colIdx = 0;
|
||||||
|
for (XSLFTableCell tc : xr) {
|
||||||
|
tc.setRowColIndex(rowIdx, colIdx);
|
||||||
|
colIdx++;
|
||||||
|
}
|
||||||
|
rowIdx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ void updateCellAnchor() {
|
||||||
|
int rows = getNumberOfRows();
|
||||||
|
int cols = getNumberOfColumns();
|
||||||
|
|
||||||
|
double colWidths[] = new double[cols];
|
||||||
|
double rowHeights[] = new double[rows];
|
||||||
|
|
||||||
|
for (int row=0; row<rows; row++) {
|
||||||
|
rowHeights[row] = getRowHeight(row);
|
||||||
|
}
|
||||||
|
for (int col=0; col<cols; col++) {
|
||||||
|
colWidths[col] = getColumnWidth(col);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle2D tblAnc = getAnchor();
|
||||||
|
DrawFactory df = DrawFactory.getInstance(null);
|
||||||
|
|
||||||
|
double newY = tblAnc.getY();
|
||||||
|
|
||||||
|
// #1 pass - determine row heights, the height values might be too low or 0 ...
|
||||||
|
for (int row=0; row<rows; row++) {
|
||||||
|
double maxHeight = 0;
|
||||||
|
for (int col=0; col<cols; col++) {
|
||||||
|
XSLFTableCell tc = getCell(row, col);
|
||||||
|
if (tc.getGridSpan() != 1 || tc.getRowSpan() != 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// need to set the anchor before height calculation
|
||||||
|
tc.setAnchor(new Rectangle2D.Double(0,0,colWidths[col],0));
|
||||||
|
DrawTextShape dts = df.getDrawable(tc);
|
||||||
|
maxHeight = Math.max(maxHeight, dts.getTextHeight());
|
||||||
|
}
|
||||||
|
rowHeights[row] = Math.max(rowHeights[row],maxHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #2 pass - init properties
|
||||||
|
for (int row=0; row<rows; row++) {
|
||||||
|
double newX = tblAnc.getX();
|
||||||
|
for (int col=0; col<cols; col++) {
|
||||||
|
Rectangle2D bounds = new Rectangle2D.Double(newX, newY, colWidths[col], rowHeights[row]);
|
||||||
|
XSLFTableCell tc = getCell(row, col);
|
||||||
|
tc.setAnchor(bounds);
|
||||||
|
newX += colWidths[col]+DrawTableShape.borderSize;
|
||||||
|
}
|
||||||
|
newY += rowHeights[row]+DrawTableShape.borderSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #3 pass - update merge info
|
||||||
|
for (int row=0; row<rows; row++) {
|
||||||
|
for (int col=0; col<cols; col++) {
|
||||||
|
XSLFTableCell tc = getCell(row, col);
|
||||||
|
Rectangle2D mergedBounds = tc.getAnchor();
|
||||||
|
for (int col2=col+1; col2<col+tc.getGridSpan(); col2++) {
|
||||||
|
assert(col2 < cols);
|
||||||
|
XSLFTableCell tc2 = getCell(row, col2);
|
||||||
|
assert(tc2.getGridSpan() == 1 && tc2.getRowSpan() == 1);
|
||||||
|
mergedBounds.add(tc2.getAnchor());
|
||||||
|
}
|
||||||
|
for (int row2=row+1; row2<row+tc.getRowSpan(); row2++) {
|
||||||
|
assert(row2 < rows);
|
||||||
|
XSLFTableCell tc2 = getCell(row2, col);
|
||||||
|
assert(tc2.getGridSpan() == 1 && tc2.getRowSpan() == 1);
|
||||||
|
mergedBounds.add(tc2.getAnchor());
|
||||||
|
}
|
||||||
|
tc.setAnchor(mergedBounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
package org.apache.poi.xslf.usermodel;
|
package org.apache.poi.xslf.usermodel;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.awt.geom.Rectangle2D;
|
||||||
|
|
||||||
import org.apache.poi.sl.draw.DrawPaint;
|
import org.apache.poi.sl.draw.DrawPaint;
|
||||||
import org.apache.poi.sl.usermodel.PaintStyle;
|
import org.apache.poi.sl.usermodel.PaintStyle;
|
||||||
@ -30,18 +31,32 @@ import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
|
|||||||
import org.apache.poi.sl.usermodel.TableCell;
|
import org.apache.poi.sl.usermodel.TableCell;
|
||||||
import org.apache.poi.sl.usermodel.VerticalAlignment;
|
import org.apache.poi.sl.usermodel.VerticalAlignment;
|
||||||
import org.apache.poi.util.Units;
|
import org.apache.poi.util.Units;
|
||||||
|
import org.apache.poi.xslf.usermodel.XSLFTableStyle.TablePartStyle;
|
||||||
|
import org.apache.xmlbeans.XmlObject;
|
||||||
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTFillProperties;
|
||||||
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTFontReference;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
|
||||||
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
|
||||||
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
|
||||||
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
|
||||||
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTTable;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCellProperties;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCellProperties;
|
||||||
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTTablePartStyle;
|
||||||
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableProperties;
|
||||||
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyleTextStyle;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
|
||||||
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
|
||||||
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.STCompoundLine;
|
import org.openxmlformats.schemas.drawingml.x2006.main.STCompoundLine;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap;
|
import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength;
|
import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType;
|
import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth;
|
import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth;
|
||||||
|
import org.openxmlformats.schemas.drawingml.x2006.main.STOnOffStyleType;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.STPenAlignment;
|
import org.openxmlformats.schemas.drawingml.x2006.main.STPenAlignment;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;
|
import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType;
|
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType;
|
||||||
@ -52,14 +67,22 @@ import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType;
|
|||||||
*/
|
*/
|
||||||
public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,XSLFTextParagraph> {
|
public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,XSLFTextParagraph> {
|
||||||
private CTTableCellProperties _tcPr = null;
|
private CTTableCellProperties _tcPr = null;
|
||||||
|
private final XSLFTable table;
|
||||||
|
private int row = 0, col = 0;
|
||||||
|
|
||||||
/*package*/ XSLFTableCell(CTTableCell cell, XSLFSheet sheet){
|
/**
|
||||||
super(cell, sheet);
|
* Volatile/temporary anchor - e.g. for rendering
|
||||||
|
*/
|
||||||
|
private Rectangle2D anchor = null;
|
||||||
|
|
||||||
|
/*package*/ XSLFTableCell(CTTableCell cell, XSLFTable table){
|
||||||
|
super(cell, table.getSheet());
|
||||||
|
this.table = table;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CTTextBody getTextBody(boolean create){
|
protected CTTextBody getTextBody(boolean create){
|
||||||
CTTableCell cell = (CTTableCell)getXmlObject();
|
CTTableCell cell = getCell();
|
||||||
CTTextBody txBody = cell.getTxBody();
|
CTTextBody txBody = cell.getTxBody();
|
||||||
if (txBody == null && create) {
|
if (txBody == null && create) {
|
||||||
txBody = cell.addNewTxBody();
|
txBody = cell.addNewTxBody();
|
||||||
@ -80,7 +103,7 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
|
|||||||
|
|
||||||
protected CTTableCellProperties getCellProperties(boolean create) {
|
protected CTTableCellProperties getCellProperties(boolean create) {
|
||||||
if (_tcPr == null) {
|
if (_tcPr == null) {
|
||||||
CTTableCell cell = (CTTableCell)getXmlObject();
|
CTTableCell cell = getCell();
|
||||||
_tcPr = cell.getTcPr();
|
_tcPr = cell.getTcPr();
|
||||||
if (_tcPr == null && create) {
|
if (_tcPr == null && create) {
|
||||||
_tcPr = cell.addNewTcPr();
|
_tcPr = cell.addNewTcPr();
|
||||||
@ -273,10 +296,9 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
|
|||||||
}
|
}
|
||||||
|
|
||||||
CTLineProperties ln = setBorderDefaults(edge);
|
CTLineProperties ln = setBorderDefaults(edge);
|
||||||
|
CTSolidColorFillProperties fill = ln.addNewSolidFill();
|
||||||
CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();
|
XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());
|
||||||
rgb.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()});
|
c.setColor(color);
|
||||||
ln.addNewSolidFill().setSrgbClr(rgb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Color getBorderColor(BorderEdge edge) {
|
public Color getBorderColor(BorderEdge edge) {
|
||||||
@ -284,12 +306,8 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
|
|||||||
if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill()) return null;
|
if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill()) return null;
|
||||||
|
|
||||||
CTSolidColorFillProperties fill = ln.getSolidFill();
|
CTSolidColorFillProperties fill = ln.getSolidFill();
|
||||||
if (!fill.isSetSrgbClr()) {
|
XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());
|
||||||
// TODO for now return null for all colors except explicit RGB
|
return c.getColor();
|
||||||
return null;
|
|
||||||
}
|
|
||||||
byte[] val = fill.getSrgbClr().getVal();
|
|
||||||
return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LineCompound getBorderCompound(BorderEdge edge) {
|
public LineCompound getBorderCompound(BorderEdge edge) {
|
||||||
@ -361,14 +379,10 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
|
|||||||
CTTableCellProperties spPr = getCellProperties(true);
|
CTTableCellProperties spPr = getCellProperties(true);
|
||||||
if (color == null) {
|
if (color == null) {
|
||||||
if(spPr.isSetSolidFill()) spPr.unsetSolidFill();
|
if(spPr.isSetSolidFill()) spPr.unsetSolidFill();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr.getSolidFill() : spPr.addNewSolidFill();
|
CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr.getSolidFill() : spPr.addNewSolidFill();
|
||||||
|
XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());
|
||||||
CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();
|
c.setColor(color);
|
||||||
rgb.setVal(new byte[]{(byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()});
|
|
||||||
|
|
||||||
fill.setSrgbClr(rgb);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,31 +393,126 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
|
|||||||
@Override
|
@Override
|
||||||
public Color getFillColor(){
|
public Color getFillColor(){
|
||||||
CTTableCellProperties spPr = getCellProperties(false);
|
CTTableCellProperties spPr = getCellProperties(false);
|
||||||
if (spPr == null || !spPr.isSetSolidFill()) return null;
|
if (spPr == null || !spPr.isSetSolidFill()) {
|
||||||
|
|
||||||
CTSolidColorFillProperties fill = spPr.getSolidFill();
|
|
||||||
if (!fill.isSetSrgbClr()) {
|
|
||||||
// TODO for now return null for all colors except explicit RGB
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
byte[] val = fill.getSrgbClr().getVal();
|
|
||||||
return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);
|
CTSolidColorFillProperties fill = spPr.getSolidFill();
|
||||||
|
XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());
|
||||||
|
return c.getColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("resource")
|
||||||
|
@Override
|
||||||
|
public PaintStyle getFillPaint() {
|
||||||
|
Color c = getFillColor();
|
||||||
|
if (c != null) {
|
||||||
|
return DrawPaint.createSolidPaint(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
CTTablePartStyle tps = getTablePartStyle(null);
|
||||||
|
if (tps == null || !tps.isSetTcStyle()) {
|
||||||
|
tps = getTablePartStyle(TablePartStyle.wholeTbl);
|
||||||
|
if (tps == null || !tps.isSetTcStyle()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XMLSlideShow slideShow = table.getSheet().getSlideShow();
|
||||||
|
assert(slideShow != null);
|
||||||
|
XSLFTheme theme = slideShow.getSlides().get(0).getTheme();
|
||||||
|
CTFillProperties pr = tps.getTcStyle().getFill();
|
||||||
|
|
||||||
|
for (XmlObject obj : pr.selectPath("*")) {
|
||||||
|
PaintStyle paint = XSLFShape.selectPaint(obj, null, slideShow.getPackagePart(), theme);
|
||||||
|
|
||||||
|
if (paint != null) {
|
||||||
|
return paint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the part style depending on the location of this cell
|
||||||
|
*
|
||||||
|
* @param tablePartStyle the part to be returned, usually this is null
|
||||||
|
* and only set when used as a helper method
|
||||||
|
* @return the table part style
|
||||||
|
*/
|
||||||
|
private CTTablePartStyle getTablePartStyle(TablePartStyle tablePartStyle) {
|
||||||
|
CTTable ct = table.getCTTable();
|
||||||
|
if (!ct.isSetTblPr()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
CTTableProperties pr = ct.getTblPr();
|
||||||
|
boolean bandRow = (pr.isSetBandRow() && pr.getBandRow());
|
||||||
|
boolean firstRow = (pr.isSetFirstRow() && pr.getFirstRow());
|
||||||
|
boolean lastRow = (pr.isSetLastRow() && pr.getLastRow());
|
||||||
|
boolean bandCol = (pr.isSetBandCol() && pr.getBandCol());
|
||||||
|
boolean firstCol = (pr.isSetFirstCol() && pr.getFirstCol());
|
||||||
|
boolean lastCol = (pr.isSetLastCol() && pr.getLastCol());
|
||||||
|
|
||||||
|
TablePartStyle tps;
|
||||||
|
if (tablePartStyle != null) {
|
||||||
|
tps = tablePartStyle;
|
||||||
|
} else if (row == 0 && firstRow) {
|
||||||
|
tps = TablePartStyle.firstRow;
|
||||||
|
} else if (row == table.getNumberOfRows()-1 && lastRow) {
|
||||||
|
tps = TablePartStyle.lastRow;
|
||||||
|
} else if (col == 0 && firstCol) {
|
||||||
|
tps = TablePartStyle.firstCol;
|
||||||
|
} else if (col == table.getNumberOfColumns()-1 && lastCol) {
|
||||||
|
tps = TablePartStyle.lastCol;
|
||||||
|
} else {
|
||||||
|
tps = TablePartStyle.wholeTbl;
|
||||||
|
|
||||||
|
int br = row + (firstRow ? 1 : 0);
|
||||||
|
int bc = col + (firstCol ? 1 : 0);
|
||||||
|
if (bandRow && (br & 1) == 0) {
|
||||||
|
tps = TablePartStyle.band1H;
|
||||||
|
} else if (bandCol && (bc & 1) == 0) {
|
||||||
|
tps = TablePartStyle.band1V;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XSLFTableStyle tabStyle = table.getTableStyle();
|
||||||
|
if (tabStyle == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
CTTablePartStyle part = tabStyle.getTablePartStyle(tps);
|
||||||
|
return (part == null) ? tabStyle.getTablePartStyle(TablePartStyle.wholeTbl) : part;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setGridSpan(int gridSpan_) {
|
void setGridSpan(int gridSpan_) {
|
||||||
((CTTableCell)getXmlObject()).setGridSpan(gridSpan_);
|
getCell().setGridSpan(gridSpan_);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getGridSpan() {
|
||||||
|
CTTableCell c = getCell();
|
||||||
|
return (c.isSetGridSpan()) ? c.getGridSpan() : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRowSpan(int rowSpan_) {
|
void setRowSpan(int rowSpan_) {
|
||||||
((CTTableCell)getXmlObject()).setRowSpan(rowSpan_);
|
getCell().setRowSpan(rowSpan_);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRowSpan() {
|
||||||
|
CTTableCell c = getCell();
|
||||||
|
return (c.isSetRowSpan()) ? c.getRowSpan() : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setHMerge(boolean merge_) {
|
void setHMerge(boolean merge_) {
|
||||||
((CTTableCell)getXmlObject()).setHMerge(merge_);
|
getCell().setHMerge(merge_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setVMerge(boolean merge_) {
|
void setVMerge(boolean merge_) {
|
||||||
((CTTableCell)getXmlObject()).setVMerge(merge_);
|
getCell().setVMerge(merge_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -491,4 +600,142 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
|
|||||||
return TextDirection.STACKED;
|
return TextDirection.STACKED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CTTableCell getCell() {
|
||||||
|
return (CTTableCell)getXmlObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ void setRowColIndex(int row, int col) {
|
||||||
|
this.row = row;
|
||||||
|
this.col = col;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a fake-xfrm which is used for calculating the text height
|
||||||
|
*/
|
||||||
|
protected CTTransform2D getXfrm() {
|
||||||
|
Rectangle2D anc = getAnchor();
|
||||||
|
CTTransform2D xfrm = CTTransform2D.Factory.newInstance();
|
||||||
|
CTPoint2D off = xfrm.addNewOff();
|
||||||
|
off.setX(Units.toEMU(anc.getX()));
|
||||||
|
off.setY(Units.toEMU(anc.getY()));
|
||||||
|
CTPositiveSize2D size = xfrm.addNewExt();
|
||||||
|
size.setCx(Units.toEMU(anc.getWidth()));
|
||||||
|
size.setCy(Units.toEMU(anc.getHeight()));
|
||||||
|
return xfrm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* There's no real anchor for table cells - this method is used to temporarily store the location
|
||||||
|
* of the cell for a later retrieval, e.g. for rendering
|
||||||
|
*
|
||||||
|
* @since POI 3.15-beta2
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setAnchor(Rectangle2D anchor) {
|
||||||
|
if (this.anchor == null) {
|
||||||
|
this.anchor = (Rectangle2D)anchor.clone();
|
||||||
|
} else {
|
||||||
|
this.anchor.setRect(anchor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since POI 3.15-beta2
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Rectangle2D getAnchor() {
|
||||||
|
if (anchor == null) {
|
||||||
|
table.updateCellAnchor();
|
||||||
|
}
|
||||||
|
// anchor should be set, after updateCellAnchor is through
|
||||||
|
assert(anchor != null);
|
||||||
|
return anchor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since POI 3.15-beta2
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isMerged() {
|
||||||
|
CTTableCell c = getCell();
|
||||||
|
return (c.isSetHMerge() && c.getHMerge()) || (c.isSetVMerge() && c.getVMerge());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since POI 3.15-beta2
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected XSLFCellTextParagraph newTextParagraph(CTTextParagraph p) {
|
||||||
|
return new XSLFCellTextParagraph(p, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since POI 3.15-beta2
|
||||||
|
*/
|
||||||
|
private class XSLFCellTextParagraph extends XSLFTextParagraph {
|
||||||
|
protected XSLFCellTextParagraph(CTTextParagraph p, XSLFTextShape shape) {
|
||||||
|
super(p, shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected XSLFCellTextRun newTextRun(CTRegularTextRun r) {
|
||||||
|
return new XSLFCellTextRun(r, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since POI 3.15-beta2
|
||||||
|
*/
|
||||||
|
private class XSLFCellTextRun extends XSLFTextRun {
|
||||||
|
protected XSLFCellTextRun(CTRegularTextRun r, XSLFTextParagraph p) {
|
||||||
|
super(r, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PaintStyle getFontColor(){
|
||||||
|
CTTableStyleTextStyle txStyle = getTextStyle();
|
||||||
|
if (txStyle == null) {
|
||||||
|
return super.getFontColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
CTSchemeColor phClr = null;
|
||||||
|
CTFontReference fontRef = txStyle.getFontRef();
|
||||||
|
if (fontRef != null) {
|
||||||
|
phClr = fontRef.getSchemeClr();
|
||||||
|
}
|
||||||
|
|
||||||
|
XSLFTheme theme = getSheet().getTheme();
|
||||||
|
final XSLFColor c = new XSLFColor(txStyle, theme, phClr);
|
||||||
|
return DrawPaint.createSolidPaint(c.getColorStyle());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBold() {
|
||||||
|
CTTableStyleTextStyle txStyle = getTextStyle();
|
||||||
|
if (txStyle == null) {
|
||||||
|
return super.isBold();
|
||||||
|
} else {
|
||||||
|
return txStyle.isSetB() && txStyle.getB().intValue() == STOnOffStyleType.INT_ON;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isItalic() {
|
||||||
|
CTTableStyleTextStyle txStyle = getTextStyle();
|
||||||
|
if (txStyle == null) {
|
||||||
|
return super.isItalic();
|
||||||
|
} else {
|
||||||
|
return txStyle.isSetI() && txStyle.getI().intValue() == STOnOffStyleType.INT_ON;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CTTableStyleTextStyle getTextStyle() {
|
||||||
|
CTTablePartStyle tps = getTablePartStyle(null);
|
||||||
|
if (tps == null || !tps.isSetTcTxStyle()) {
|
||||||
|
tps = getTablePartStyle(TablePartStyle.wholeTbl);
|
||||||
|
}
|
||||||
|
return (tps == null) ? null : tps.getTcTxStyle();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -30,8 +30,6 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTTableRow;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a table in a .pptx presentation
|
* Represents a table in a .pptx presentation
|
||||||
*
|
|
||||||
* @author Yegor Kozlov
|
|
||||||
*/
|
*/
|
||||||
public class XSLFTableRow implements Iterable<XSLFTableCell> {
|
public class XSLFTableRow implements Iterable<XSLFTableCell> {
|
||||||
private CTTableRow _row;
|
private CTTableRow _row;
|
||||||
@ -44,7 +42,7 @@ public class XSLFTableRow implements Iterable<XSLFTableCell> {
|
|||||||
CTTableCell[] tcArray = _row.getTcArray();
|
CTTableCell[] tcArray = _row.getTcArray();
|
||||||
_cells = new ArrayList<XSLFTableCell>(tcArray.length);
|
_cells = new ArrayList<XSLFTableCell>(tcArray.length);
|
||||||
for(CTTableCell cell : tcArray) {
|
for(CTTableCell cell : tcArray) {
|
||||||
_cells.add(new XSLFTableCell(cell, table.getSheet()));
|
_cells.add(new XSLFTableCell(cell, table));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,12 +69,13 @@ public class XSLFTableRow implements Iterable<XSLFTableCell> {
|
|||||||
public XSLFTableCell addCell(){
|
public XSLFTableCell addCell(){
|
||||||
CTTableCell c = _row.addNewTc();
|
CTTableCell c = _row.addNewTc();
|
||||||
c.set(XSLFTableCell.prototype());
|
c.set(XSLFTableCell.prototype());
|
||||||
XSLFTableCell cell = new XSLFTableCell(c, _table.getSheet());
|
XSLFTableCell cell = new XSLFTableCell(c, _table);
|
||||||
_cells.add(cell);
|
_cells.add(cell);
|
||||||
|
|
||||||
if(_table.getNumberOfColumns() < _row.sizeOfTcArray()) {
|
if(_table.getNumberOfColumns() < _row.sizeOfTcArray()) {
|
||||||
_table.getCTTable().getTblGrid().addNewGridCol().setW(Units.toEMU(100.0));
|
_table.getCTTable().getTblGrid().addNewGridCol().setW(Units.toEMU(100.0));
|
||||||
}
|
}
|
||||||
|
_table.updateRowColIndexes();
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,16 +19,19 @@
|
|||||||
|
|
||||||
package org.apache.poi.xslf.usermodel;
|
package org.apache.poi.xslf.usermodel;
|
||||||
|
|
||||||
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTTablePartStyle;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyle;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a table in a .pptx presentation
|
* Represents a table style in a .pptx presentation
|
||||||
*
|
|
||||||
* @author Yegor Kozlov
|
|
||||||
*/
|
*/
|
||||||
public class XSLFTableStyle {
|
public class XSLFTableStyle {
|
||||||
private CTTableStyle _tblStyle;
|
private CTTableStyle _tblStyle;
|
||||||
|
|
||||||
|
public enum TablePartStyle {
|
||||||
|
wholeTbl, band1H, band2H, band1V, band2V, firstCol, lastCol, firstRow, lastRow, seCell, swCell, neCell, nwCell;
|
||||||
|
}
|
||||||
|
|
||||||
/*package*/ XSLFTableStyle(CTTableStyle style){
|
/*package*/ XSLFTableStyle(CTTableStyle style){
|
||||||
_tblStyle = style;
|
_tblStyle = style;
|
||||||
}
|
}
|
||||||
@ -44,4 +47,39 @@ public class XSLFTableStyle {
|
|||||||
public String getStyleId(){
|
public String getStyleId(){
|
||||||
return _tblStyle.getStyleId();
|
return _tblStyle.getStyleId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since POI 3.15-beta2
|
||||||
|
*/
|
||||||
|
protected CTTablePartStyle getTablePartStyle(TablePartStyle tps) {
|
||||||
|
switch (tps) {
|
||||||
|
default:
|
||||||
|
case wholeTbl:
|
||||||
|
return _tblStyle.getWholeTbl();
|
||||||
|
case band1H:
|
||||||
|
return _tblStyle.getBand1H();
|
||||||
|
case band2H:
|
||||||
|
return _tblStyle.getBand2H();
|
||||||
|
case band1V:
|
||||||
|
return _tblStyle.getBand1V();
|
||||||
|
case band2V:
|
||||||
|
return _tblStyle.getBand2V();
|
||||||
|
case firstCol:
|
||||||
|
return _tblStyle.getFirstCol();
|
||||||
|
case lastCol:
|
||||||
|
return _tblStyle.getLastCol();
|
||||||
|
case firstRow:
|
||||||
|
return _tblStyle.getFirstRow();
|
||||||
|
case lastRow:
|
||||||
|
return _tblStyle.getLastRow();
|
||||||
|
case seCell:
|
||||||
|
return _tblStyle.getSeCell();
|
||||||
|
case swCell:
|
||||||
|
return _tblStyle.getSwCell();
|
||||||
|
case neCell:
|
||||||
|
return _tblStyle.getNeCell();
|
||||||
|
case nwCell:
|
||||||
|
return _tblStyle.getNwCell();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -16,9 +16,8 @@
|
|||||||
==================================================================== */
|
==================================================================== */
|
||||||
package org.apache.poi.xslf.usermodel;
|
package org.apache.poi.xslf.usermodel;
|
||||||
|
|
||||||
import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -31,6 +30,7 @@ import org.apache.poi.util.Beta;
|
|||||||
import org.apache.xmlbeans.XmlException;
|
import org.apache.xmlbeans.XmlException;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyle;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyle;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyleList;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyleList;
|
||||||
|
import org.openxmlformats.schemas.drawingml.x2006.main.TblStyleLstDocument;
|
||||||
|
|
||||||
@Beta
|
@Beta
|
||||||
public class XSLFTableStyles extends POIXMLDocumentPart implements Iterable<XSLFTableStyle>{
|
public class XSLFTableStyles extends POIXMLDocumentPart implements Iterable<XSLFTableStyle>{
|
||||||
@ -47,7 +47,10 @@ public class XSLFTableStyles extends POIXMLDocumentPart implements Iterable<XSLF
|
|||||||
public XSLFTableStyles(PackagePart part) throws IOException, XmlException {
|
public XSLFTableStyles(PackagePart part) throws IOException, XmlException {
|
||||||
super(part);
|
super(part);
|
||||||
|
|
||||||
_tblStyleLst = CTTableStyleList.Factory.parse(getPackagePart().getInputStream(), DEFAULT_XML_OPTIONS);
|
InputStream is = getPackagePart().getInputStream();
|
||||||
|
TblStyleLstDocument styleDoc = TblStyleLstDocument.Factory.parse(is);
|
||||||
|
is.close();
|
||||||
|
_tblStyleLst = styleDoc.getTblStyleLst();
|
||||||
CTTableStyle[] tblStyleArray = _tblStyleLst.getTblStyleArray();
|
CTTableStyle[] tblStyleArray = _tblStyleLst.getTblStyleArray();
|
||||||
_styles = new ArrayList<XSLFTableStyle>(tblStyleArray.length);
|
_styles = new ArrayList<XSLFTableStyle>(tblStyleArray.length);
|
||||||
for(CTTableStyle c : tblStyleArray){
|
for(CTTableStyle c : tblStyleArray){
|
||||||
|
@ -59,7 +59,6 @@ import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
|
|||||||
* Represents a paragraph of text within the containing text body.
|
* Represents a paragraph of text within the containing text body.
|
||||||
* The paragraph is the highest level text separation mechanism.
|
* The paragraph is the highest level text separation mechanism.
|
||||||
*
|
*
|
||||||
* @author Yegor Kozlov
|
|
||||||
* @since POI-3.8
|
* @since POI-3.8
|
||||||
*/
|
*/
|
||||||
@Beta
|
@Beta
|
||||||
@ -76,19 +75,19 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr
|
|||||||
for(XmlObject ch : _p.selectPath("*")){
|
for(XmlObject ch : _p.selectPath("*")){
|
||||||
if(ch instanceof CTRegularTextRun){
|
if(ch instanceof CTRegularTextRun){
|
||||||
CTRegularTextRun r = (CTRegularTextRun)ch;
|
CTRegularTextRun r = (CTRegularTextRun)ch;
|
||||||
_runs.add(new XSLFTextRun(r, this));
|
_runs.add(newTextRun(r));
|
||||||
} else if (ch instanceof CTTextLineBreak){
|
} else if (ch instanceof CTTextLineBreak){
|
||||||
CTTextLineBreak br = (CTTextLineBreak)ch;
|
CTTextLineBreak br = (CTTextLineBreak)ch;
|
||||||
CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
|
CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
|
||||||
r.setRPr(br.getRPr());
|
r.setRPr(br.getRPr());
|
||||||
r.setT("\n");
|
r.setT("\n");
|
||||||
_runs.add(new XSLFTextRun(r, this));
|
_runs.add(newTextRun(r));
|
||||||
} else if (ch instanceof CTTextField){
|
} else if (ch instanceof CTTextField){
|
||||||
CTTextField f = (CTTextField)ch;
|
CTTextField f = (CTTextField)ch;
|
||||||
CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
|
CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
|
||||||
r.setRPr(f.getRPr());
|
r.setRPr(f.getRPr());
|
||||||
r.setT(f.getT());
|
r.setT(f.getT());
|
||||||
_runs.add(new XSLFTextRun(r, this));
|
_runs.add(newTextRun(r));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,7 +136,7 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr
|
|||||||
CTRegularTextRun r = _p.addNewR();
|
CTRegularTextRun r = _p.addNewR();
|
||||||
CTTextCharacterProperties rPr = r.addNewRPr();
|
CTTextCharacterProperties rPr = r.addNewRPr();
|
||||||
rPr.setLang("en-US");
|
rPr.setLang("en-US");
|
||||||
XSLFTextRun run = new XSLFTextRun(r, this);
|
XSLFTextRun run = newTextRun(r);
|
||||||
_runs.add(run);
|
_runs.add(run);
|
||||||
return run;
|
return run;
|
||||||
}
|
}
|
||||||
@ -774,22 +773,23 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr
|
|||||||
int level = getIndentLevel();
|
int level = getIndentLevel();
|
||||||
|
|
||||||
// wind up and find the root master sheet which must be slide master
|
// wind up and find the root master sheet which must be slide master
|
||||||
final String nsDecl =
|
final String nsPML = "http://schemas.openxmlformats.org/presentationml/2006/main";
|
||||||
"declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " +
|
final String nsDML = "http://schemas.openxmlformats.org/drawingml/2006/main";
|
||||||
"declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' ";
|
|
||||||
final String xpaths[] = {
|
|
||||||
nsDecl+".//p:txStyles/p:" + defaultStyleSelector +"/a:lvl" +(level+1)+ "pPr",
|
|
||||||
nsDecl+".//p:notesStyle/a:lvl" +(level+1)+ "pPr"
|
|
||||||
};
|
|
||||||
XSLFSheet masterSheet = _shape.getSheet();
|
XSLFSheet masterSheet = _shape.getSheet();
|
||||||
for (XSLFSheet m = masterSheet; m != null; m = (XSLFSheet)m.getMasterSheet()) {
|
for (XSLFSheet m = masterSheet; m != null; m = (XSLFSheet)m.getMasterSheet()) {
|
||||||
masterSheet = m;
|
masterSheet = m;
|
||||||
XmlObject xo = masterSheet.getXmlObject();
|
XmlObject xo = masterSheet.getXmlObject();
|
||||||
for (String xpath : xpaths) {
|
XmlCursor cur = xo.newCursor();
|
||||||
XmlObject[] o = xo.selectPath(xpath);
|
try {
|
||||||
if (o.length == 1) {
|
cur.push();
|
||||||
return (CTTextParagraphProperties)o[0];
|
if ((cur.toChild(nsPML, "txStyles") && cur.toChild(nsPML, defaultStyleSelector)) ||
|
||||||
|
(cur.pop() && cur.toChild(nsPML, "notesStyle"))) {
|
||||||
|
if (cur.toChild(nsDML, "lvl" +(level+1)+ "pPr")) {
|
||||||
|
return (CTTextParagraphProperties)cur.getObject();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
cur.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -880,7 +880,7 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr
|
|||||||
List<XSLFTextRun> otherRs = other.getTextRuns();
|
List<XSLFTextRun> otherRs = other.getTextRuns();
|
||||||
int i=0;
|
int i=0;
|
||||||
for(CTRegularTextRun rtr : thisP.getRArray()) {
|
for(CTRegularTextRun rtr : thisP.getRArray()) {
|
||||||
XSLFTextRun run = new XSLFTextRun(rtr, this);
|
XSLFTextRun run = newTextRun(rtr);
|
||||||
run.copy(otherRs.get(i++));
|
run.copy(otherRs.get(i++));
|
||||||
_runs.add(run);
|
_runs.add(run);
|
||||||
}
|
}
|
||||||
@ -949,6 +949,9 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr
|
|||||||
@Override
|
@Override
|
||||||
public Double getDefaultFontSize() {
|
public Double getDefaultFontSize() {
|
||||||
CTTextCharacterProperties endPr = _p.getEndParaRPr();
|
CTTextCharacterProperties endPr = _p.getEndParaRPr();
|
||||||
|
if (endPr == null || !endPr.isSetSz()) {
|
||||||
|
endPr = getDefaultMasterStyle().getDefRPr();
|
||||||
|
}
|
||||||
return (endPr == null || !endPr.isSetSz()) ? 12 : (endPr.getSz() / 100.);
|
return (endPr == null || !endPr.isSetSz()) ? 12 : (endPr.getSz() / 100.);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1062,4 +1065,17 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to allow subclasses to provide their own text run
|
||||||
|
*
|
||||||
|
* @param r the xml reference
|
||||||
|
*
|
||||||
|
* @return a new text paragraph
|
||||||
|
*
|
||||||
|
* @since POI 3.15-beta2
|
||||||
|
*/
|
||||||
|
protected XSLFTextRun newTextRun(CTRegularTextRun r) {
|
||||||
|
return new XSLFTextRun(r, this);
|
||||||
|
}
|
||||||
}
|
}
|
@ -30,15 +30,13 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
|
|||||||
/**
|
/**
|
||||||
* Represents a run of text within the containing text body. The run element is the
|
* Represents a run of text within the containing text body. The run element is the
|
||||||
* lowest level text separation mechanism within a text body.
|
* lowest level text separation mechanism within a text body.
|
||||||
*
|
|
||||||
* @author Yegor Kozlov
|
|
||||||
*/
|
*/
|
||||||
@Beta
|
@Beta
|
||||||
public class XSLFTextRun implements TextRun {
|
public class XSLFTextRun implements TextRun {
|
||||||
private final CTRegularTextRun _r;
|
private final CTRegularTextRun _r;
|
||||||
private final XSLFTextParagraph _p;
|
private final XSLFTextParagraph _p;
|
||||||
|
|
||||||
XSLFTextRun(CTRegularTextRun r, XSLFTextParagraph p){
|
protected XSLFTextRun(CTRegularTextRun r, XSLFTextParagraph p){
|
||||||
_r = r;
|
_r = r;
|
||||||
_p = p;
|
_p = p;
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
|
|||||||
CTTextBody txBody = getTextBody(false);
|
CTTextBody txBody = getTextBody(false);
|
||||||
if (txBody != null) {
|
if (txBody != null) {
|
||||||
for (CTTextParagraph p : txBody.getPArray()) {
|
for (CTTextParagraph p : txBody.getPArray()) {
|
||||||
_paragraphs.add(new XSLFTextParagraph(p, this));
|
_paragraphs.add(newTextParagraph(p));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -184,7 +184,7 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
|
|||||||
} else {
|
} else {
|
||||||
p = txBody.addNewP();
|
p = txBody.addNewP();
|
||||||
}
|
}
|
||||||
XSLFTextParagraph paragraph = new XSLFTextParagraph(p, this);
|
XSLFTextParagraph paragraph = newTextParagraph(p);
|
||||||
_paragraphs.add(paragraph);
|
_paragraphs.add(paragraph);
|
||||||
return paragraph;
|
return paragraph;
|
||||||
}
|
}
|
||||||
@ -654,5 +654,16 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to allow subclasses to provide their own text paragraph
|
||||||
|
*
|
||||||
|
* @param p the xml reference
|
||||||
|
*
|
||||||
|
* @return a new text paragraph
|
||||||
|
*
|
||||||
|
* @since POI 3.15-beta2
|
||||||
|
*/
|
||||||
|
protected XSLFTextParagraph newTextParagraph(CTTextParagraph p) {
|
||||||
|
return new XSLFTextParagraph(p, this);
|
||||||
|
}
|
||||||
}
|
}
|
@ -19,27 +19,20 @@ package org.apache.poi.xslf.usermodel;
|
|||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
import org.junit.Test;
|
import java.io.IOException;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyle;
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Yegor Kozlov
|
|
||||||
*/
|
|
||||||
public class TestXSLFTableStyles {
|
public class TestXSLFTableStyles {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRead(){
|
public void testRead() throws IOException {
|
||||||
XMLSlideShow ppt = new XMLSlideShow();
|
XMLSlideShow ppt = new XMLSlideShow();
|
||||||
XSLFTableStyles tblStyles = ppt.getTableStyles();
|
XSLFTableStyles tblStyles = ppt.getTableStyles();
|
||||||
assertNotNull(tblStyles);
|
assertNotNull(tblStyles);
|
||||||
|
|
||||||
assertEquals(0, tblStyles.getStyles().size());
|
assertEquals(0, tblStyles.getStyles().size());
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
ppt.close();
|
||||||
@Test
|
|
||||||
public void testStyle(){
|
|
||||||
CTTableStyle obj = CTTableStyle.Factory.newInstance();
|
|
||||||
XSLFTableStyle style = new XSLFTableStyle(obj);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -18,13 +18,12 @@
|
|||||||
package org.apache.poi.hslf.usermodel;
|
package org.apache.poi.hslf.usermodel;
|
||||||
|
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import org.apache.poi.ddf.AbstractEscherOptRecord;
|
import org.apache.poi.ddf.AbstractEscherOptRecord;
|
||||||
import org.apache.poi.ddf.EscherArrayProperty;
|
import org.apache.poi.ddf.EscherArrayProperty;
|
||||||
@ -170,23 +169,6 @@ implements HSLFShapeContainer, TableShape<HSLFShape,HSLFTextParagraph> {
|
|||||||
updateRowHeightsProperty();
|
updateRowHeightsProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class TableCellComparator implements Comparator<HSLFShape>, Serializable {
|
|
||||||
public int compare( HSLFShape o1, HSLFShape o2 ) {
|
|
||||||
Rectangle2D anchor1 = o1.getAnchor();
|
|
||||||
Rectangle2D anchor2 = o2.getAnchor();
|
|
||||||
double delta = anchor1.getY() - anchor2.getY();
|
|
||||||
if (delta == 0) {
|
|
||||||
delta = anchor1.getX() - anchor2.getX();
|
|
||||||
}
|
|
||||||
// descending size
|
|
||||||
if (delta == 0) {
|
|
||||||
delta = (anchor2.getWidth()*anchor2.getHeight())-(anchor1.getWidth()*anchor1.getHeight());
|
|
||||||
}
|
|
||||||
|
|
||||||
return (int)Math.signum(delta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cellListToArray() {
|
private void cellListToArray() {
|
||||||
List<HSLFTableCell> htc = new ArrayList<HSLFTableCell>();
|
List<HSLFTableCell> htc = new ArrayList<HSLFTableCell>();
|
||||||
for (HSLFShape h : getShapes()) {
|
for (HSLFShape h : getShapes()) {
|
||||||
@ -199,25 +181,49 @@ implements HSLFShapeContainer, TableShape<HSLFShape,HSLFTextParagraph> {
|
|||||||
throw new IllegalStateException("HSLFTable without HSLFTableCells");
|
throw new IllegalStateException("HSLFTable without HSLFTableCells");
|
||||||
}
|
}
|
||||||
|
|
||||||
Collections.sort(htc, new TableCellComparator());
|
SortedSet<Double> colSet = new TreeSet<Double>();
|
||||||
|
SortedSet<Double> rowSet = new TreeSet<Double>();
|
||||||
|
|
||||||
List<HSLFTableCell[]> lst = new ArrayList<HSLFTableCell[]>();
|
// #1 pass - determine cols and rows
|
||||||
List<HSLFTableCell> row = new ArrayList<HSLFTableCell>();
|
|
||||||
|
|
||||||
double y0 = htc.get(0).getAnchor().getY();
|
|
||||||
for (HSLFTableCell sh : htc) {
|
for (HSLFTableCell sh : htc) {
|
||||||
Rectangle2D anchor = sh.getAnchor();
|
Rectangle2D anchor = sh.getAnchor();
|
||||||
boolean isNextRow = (anchor.getY() > y0);
|
colSet.add(anchor.getX());
|
||||||
if (isNextRow) {
|
rowSet.add(anchor.getY());
|
||||||
y0 = anchor.getY();
|
|
||||||
lst.add(row.toArray(new HSLFTableCell[row.size()]));
|
|
||||||
row.clear();
|
|
||||||
}
|
|
||||||
row.add(sh);
|
|
||||||
}
|
}
|
||||||
lst.add(row.toArray(new HSLFTableCell[row.size()]));
|
cells = new HSLFTableCell[rowSet.size()][colSet.size()];
|
||||||
|
|
||||||
cells = lst.toArray(new HSLFTableCell[lst.size()][]);
|
List<Double> colLst = new ArrayList<Double>(colSet);
|
||||||
|
List<Double> rowLst = new ArrayList<Double>(rowSet);
|
||||||
|
|
||||||
|
// #2 pass - assign shape to table cells
|
||||||
|
for (HSLFTableCell sh : htc) {
|
||||||
|
Rectangle2D anchor = sh.getAnchor();
|
||||||
|
int row = rowLst.indexOf(anchor.getY());
|
||||||
|
int col = colLst.indexOf(anchor.getX());
|
||||||
|
assert(row != -1 && col != -1);
|
||||||
|
cells[row][col] = sh;
|
||||||
|
|
||||||
|
// determine gridSpan / rowSpan
|
||||||
|
int gridSpan = calcSpan(colLst, anchor.getWidth(), col);
|
||||||
|
int rowSpan = calcSpan(rowLst, anchor.getHeight(), row);
|
||||||
|
|
||||||
|
sh.setGridSpan(gridSpan);
|
||||||
|
sh.setRowSpan(rowSpan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int calcSpan(List<Double> spaces, double totalSpace, int idx) {
|
||||||
|
if (idx == spaces.size()-1) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int span = 0;
|
||||||
|
double remainingSpace = totalSpace;
|
||||||
|
while (idx+1 < spaces.size() && remainingSpace > 0) {
|
||||||
|
remainingSpace -= spaces.get(idx+1)-spaces.get(idx);
|
||||||
|
span++;
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
return span;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class LineRect {
|
static class LineRect {
|
||||||
@ -258,6 +264,9 @@ implements HSLFShapeContainer, TableShape<HSLFShape,HSLFTextParagraph> {
|
|||||||
// TODO: this only works for non-rotated tables
|
// TODO: this only works for non-rotated tables
|
||||||
for (HSLFTableCell[] tca : cells) {
|
for (HSLFTableCell[] tca : cells) {
|
||||||
for (HSLFTableCell tc : tca) {
|
for (HSLFTableCell tc : tca) {
|
||||||
|
if (tc == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
final Rectangle2D cellAnchor = tc.getAnchor();
|
final Rectangle2D cellAnchor = tc.getAnchor();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,8 +33,6 @@ import org.apache.poi.sl.usermodel.TableCell;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a cell in a ppt table
|
* Represents a cell in a ppt table
|
||||||
*
|
|
||||||
* @author Yegor Kozlov
|
|
||||||
*/
|
*/
|
||||||
public final class HSLFTableCell extends HSLFTextBox implements TableCell<HSLFShape,HSLFTextParagraph> {
|
public final class HSLFTableCell extends HSLFTextBox implements TableCell<HSLFShape,HSLFTextParagraph> {
|
||||||
protected static final int DEFAULT_WIDTH = 100;
|
protected static final int DEFAULT_WIDTH = 100;
|
||||||
@ -45,6 +43,16 @@ public final class HSLFTableCell extends HSLFTextBox implements TableCell<HSLFSh
|
|||||||
/* package */ HSLFLine borderTop;
|
/* package */ HSLFLine borderTop;
|
||||||
/* package */ HSLFLine borderBottom;
|
/* package */ HSLFLine borderBottom;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of columns to be spanned/merged
|
||||||
|
*/
|
||||||
|
private int gridSpan = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of columns to be spanned/merged
|
||||||
|
*/
|
||||||
|
private int rowSpan = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a TableCell object and initialize it from the supplied Record container.
|
* Create a TableCell object and initialize it from the supplied Record container.
|
||||||
*
|
*
|
||||||
@ -397,4 +405,43 @@ public final class HSLFTableCell extends HSLFTextBox implements TableCell<HSLFSh
|
|||||||
public HSLFTable getParent() {
|
public HSLFTable getParent() {
|
||||||
return (HSLFTable)super.getParent();
|
return (HSLFTable)super.getParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the gridSpan (aka col-span)
|
||||||
|
*
|
||||||
|
* @param gridSpan the number of columns to be spanned/merged
|
||||||
|
*
|
||||||
|
* @since POI 3.15-beta2
|
||||||
|
*/
|
||||||
|
protected void setGridSpan(int gridSpan) {
|
||||||
|
this.gridSpan = gridSpan;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the rowSpan
|
||||||
|
*
|
||||||
|
* @param rowSpan the number of rows to be spanned/merged
|
||||||
|
*
|
||||||
|
* @since POI 3.15-beta2
|
||||||
|
*/
|
||||||
|
protected void setRowSpan(int rowSpan) {
|
||||||
|
this.rowSpan = rowSpan;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getGridSpan() {
|
||||||
|
return gridSpan;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRowSpan() {
|
||||||
|
return rowSpan;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isMerged() {
|
||||||
|
// if a hslf cell is merged, it won't appear in the cell matrix, i.e. it doesn't exist
|
||||||
|
// therefore this is always false
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user