Common sl unification - copy first paragraph / textrun properties on XSLFTextShape.setText()

Common sl unification - converted ApacheconEU08 example to common sl - added missing functionality
Common sl unification - return null instead of default values for missing borders X/HSLFTable
Common sl unification - use points in HSLFTable.setColumnWidth()
Fix appending text to empty HSLFTextParagraph


git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1711171 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2015-10-29 01:05:27 +00:00
parent 632228a34e
commit 1d1bdc1521
57 changed files with 4058 additions and 1159 deletions

View File

@ -26,19 +26,20 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import org.apache.poi.hslf.model.PPGraphics2D;
import org.apache.poi.hslf.record.TextHeaderAtom;
import org.apache.poi.hslf.usermodel.HSLFAutoShape;
import org.apache.poi.hslf.usermodel.HSLFGroupShape;
import org.apache.poi.hslf.usermodel.HSLFSlide;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
import org.apache.poi.hslf.usermodel.HSLFTable;
import org.apache.poi.hslf.usermodel.HSLFTableCell;
import org.apache.poi.hslf.usermodel.HSLFTextBox;
import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
import org.apache.poi.hslf.usermodel.HSLFTextRun;
import org.apache.poi.hslf.usermodel.HSLFLine;
import org.apache.poi.sl.draw.DrawTableShape;
import org.apache.poi.sl.draw.SLGraphics;
import org.apache.poi.sl.usermodel.AutoShape;
import org.apache.poi.sl.usermodel.GroupShape;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.sl.usermodel.Slide;
import org.apache.poi.sl.usermodel.SlideShow;
import org.apache.poi.sl.usermodel.TableCell;
import org.apache.poi.sl.usermodel.TableShape;
import org.apache.poi.sl.usermodel.TextBox;
import org.apache.poi.sl.usermodel.TextParagraph;
import org.apache.poi.sl.usermodel.TextRun;
import org.apache.poi.sl.usermodel.TextShape.TextPlaceholder;
import org.apache.poi.sl.usermodel.VerticalAlignment;
/**
@ -49,7 +50,8 @@ import org.apache.poi.sl.usermodel.VerticalAlignment;
public final class ApacheconEU08 {
public static void main(String[] args) throws IOException {
HSLFSlideShow ppt = new HSLFSlideShow();
SlideShow<?,?> ppt = new HSLFSlideShow();
// SlideShow<?,?> ppt = new XMLSlideShow();
ppt.setPageSize(new Dimension(720, 540));
slide1(ppt);
@ -65,69 +67,62 @@ public final class ApacheconEU08 {
slide11(ppt);
slide12(ppt);
FileOutputStream out = new FileOutputStream("apachecon_eu_08.ppt");
String ext = ppt.getClass().getName().contains("HSLF") ? "ppt" : "pptx";
FileOutputStream out = new FileOutputStream("apachecon_eu_08."+ext);
ppt.write(out);
out.close();
}
public static void slide1(HSLFSlideShow ppt) throws IOException {
HSLFSlide slide = ppt.createSlide();
public static void slide1(SlideShow<?,?> ppt) throws IOException {
Slide<?,?> slide = ppt.createSlide();
HSLFTextBox box1 = new HSLFTextBox();
box1.setRunType(TextHeaderAtom.CENTER_TITLE_TYPE);
TextBox<?,?> box1 = slide.createTextBox();
box1.setTextPlaceholder(TextPlaceholder.CENTER_TITLE);
box1.setText("POI-HSLF");
box1.setAnchor(new Rectangle(54, 78, 612, 115));
slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox();
box2.setRunType(TextHeaderAtom.CENTRE_BODY_TYPE);
TextBox<?,?> box2 = slide.createTextBox();
box2.setTextPlaceholder(TextPlaceholder.CENTER_BODY);
box2.setText("Java API To Access Microsoft PowerPoint Format Files");
box2.setAnchor(new Rectangle(108, 204, 504, 138));
slide.addShape(box2);
HSLFTextBox box3 = new HSLFTextBox();
TextBox<?,?> box3 = slide.createTextBox();
box3.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(32d);
box3.setText(
"Yegor Kozlov\r" +
"yegor - apache - org");
box3.setHorizontalCentered(true);
box3.setAnchor(new Rectangle(206, 348, 310, 84));
slide.addShape(box3);
}
public static void slide2(HSLFSlideShow ppt) throws IOException {
HSLFSlide slide = ppt.createSlide();
public static void slide2(SlideShow<?,?> ppt) throws IOException {
Slide<?,?> slide = ppt.createSlide();
HSLFTextBox box1 = new HSLFTextBox();
box1.setRunType(TextHeaderAtom.TITLE_TYPE);
TextBox<?,?> box1 = slide.createTextBox();
box1.setTextPlaceholder(TextPlaceholder.TITLE);
box1.setText("What is HSLF?");
box1.setAnchor(new Rectangle(36, 21, 648, 90));
slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox();
box2.setRunType(TextHeaderAtom.BODY_TYPE);
TextBox<?,?> box2 = slide.createTextBox();
box2.setTextPlaceholder(TextPlaceholder.BODY);
box2.setText("HorribleSLideshowFormat is the POI Project's pure Java implementation " +
"of the Powerpoint binary file format. \r" +
"POI sub-project since 2005\r" +
"Started by Nick Birch, Yegor Kozlov joined soon after");
"Started by Nick Burch, Yegor Kozlov joined soon after");
box2.setAnchor(new Rectangle(36, 126, 648, 356));
slide.addShape(box2);
}
public static void slide3(HSLFSlideShow ppt) throws IOException {
HSLFSlide slide = ppt.createSlide();
public static void slide3(SlideShow<?,?> ppt) throws IOException {
Slide<?,?> slide = ppt.createSlide();
HSLFTextBox box1 = new HSLFTextBox();
box1.setRunType(TextHeaderAtom.TITLE_TYPE);
TextBox<?,?> box1 = slide.createTextBox();
box1.setTextPlaceholder(TextPlaceholder.TITLE);
box1.setText("HSLF in a Nutshell");
box1.setAnchor(new Rectangle(36, 15, 648, 65));
slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox();
box2.setRunType(TextHeaderAtom.BODY_TYPE);
TextBox<?,?> box2 = slide.createTextBox();
box2.setTextPlaceholder(TextPlaceholder.BODY);
box2.setText(
"HSLF provides a way to read, create and modify MS PowerPoint presentations\r" +
"Pure Java API - you don't need PowerPoint to read and write *.ppt files\r" +
@ -140,7 +135,7 @@ public final class ApacheconEU08 {
"Access to low level data structures"
);
List<HSLFTextParagraph> tp = box2.getTextParagraphs();
List<? extends TextParagraph<?,?,?>> tp = box2.getTextParagraphs();
for (int i : new byte[]{0,1,2,8}) {
tp.get(i).getTextRuns().get(0).setFontSize(28d);
}
@ -149,102 +144,88 @@ public final class ApacheconEU08 {
tp.get(i).setIndentLevel(1);
}
box2.setAnchor(new Rectangle(36, 80, 648, 400));
slide.addShape(box2);
}
public static void slide4(HSLFSlideShow ppt) throws IOException {
HSLFSlide slide = ppt.createSlide();
public static void slide4(SlideShow<?,?> ppt) throws IOException {
Slide<?,?> slide = ppt.createSlide();
String[][] txt1 = {
{"Note"},
{"This presentation was created programmatically using POI HSLF"}
};
HSLFTable table1 = new HSLFTable(2, 1);
TableShape<?,?> table1 = slide.createTable(2, 1);
for (int i = 0; i < txt1.length; i++) {
for (int j = 0; j < txt1[i].length; j++) {
HSLFTableCell cell = table1.getCell(i, j);
TableCell<?,?> cell = table1.getCell(i, j);
cell.setText(txt1[i][j]);
HSLFTextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0);
TextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0);
rt.setFontSize(10d);
rt.setFontFamily("Arial");
rt.setBold(true);
if(i == 0){
rt.setFontSize(32d);
rt.setFontColor(Color.white);
cell.getFill().setForegroundColor(new Color(0, 153, 204));
cell.setFillColor(new Color(0, 153, 204));
} else {
rt.setFontSize(28d);
cell.getFill().setForegroundColor(new Color(235, 239, 241));
cell.setFillColor(new Color(235, 239, 241));
}
cell.setVerticalAlignment(VerticalAlignment.MIDDLE);
}
}
HSLFLine border1 = table1.createBorder();
border1.setLineColor(Color.black);
border1.setLineWidth(1.0);
table1.setAllBorders(border1);
DrawTableShape dts = new DrawTableShape(table1);
dts.setAllBorders(1.0, Color.black);
dts.setOutsideBorders(4.0);
HSLFLine border2 = table1.createBorder();
border2.setLineColor(Color.black);
border2.setLineWidth(2.0);
table1.setOutsideBorders(border2);
table1.setColumnWidth(0, 450);
table1.setRowHeight(0, 50);
table1.setRowHeight(1, 80);
table1.setColumnWidth(0, 510);
table1.setRowHeight(0, 60);
table1.setRowHeight(1, 100);
slide.addShape(table1);
Dimension dim = ppt.getPageSize();
Rectangle oldAnchor = table1.getAnchor();
table1.setAnchor(new Rectangle((dim.width-450)/2, 100, oldAnchor.width, oldAnchor.height));
table1.moveTo(100, 100);
HSLFTextBox box1 = new HSLFTextBox();
TextBox<?,?> box1 = slide.createTextBox();
box1.setHorizontalCentered(true);
box1.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(24d);
box1.setText("The source code is available at\r" +
"http://people.apache.org/~yegor/apachecon_eu08/");
box1.setAnchor(new Rectangle(80, 356, 553, 65));
slide.addShape(box1);
}
public static void slide5(HSLFSlideShow ppt) throws IOException {
HSLFSlide slide = ppt.createSlide();
public static void slide5(SlideShow<?,?> ppt) throws IOException {
Slide<?,?> slide = ppt.createSlide();
HSLFTextBox box1 = new HSLFTextBox();
box1.setRunType(TextHeaderAtom.TITLE_TYPE);
TextBox<?,?> box1 = slide.createTextBox();
box1.setTextPlaceholder(TextPlaceholder.TITLE);
box1.setText("HSLF in Action - 1\rData Extraction");
box1.setAnchor(new Rectangle(36, 21, 648, 100));
slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox();
box2.setRunType(TextHeaderAtom.BODY_TYPE);
TextBox<?,?> box2 = slide.createTextBox();
box2.setTextPlaceholder(TextPlaceholder.BODY);
box2.setText(
"Text from slides and notes\r" +
"Images\r" +
"Shapes and their properties (type, position in the slide, color, font, etc.)");
box2.setAnchor(new Rectangle(36, 150, 648, 300));
slide.addShape(box2);
}
public static void slide6(HSLFSlideShow ppt) throws IOException {
HSLFSlide slide = ppt.createSlide();
public static void slide6(SlideShow<?,?> ppt) throws IOException {
Slide<?,?> slide = ppt.createSlide();
HSLFTextBox box1 = new HSLFTextBox();
box1.setRunType(TextHeaderAtom.TITLE_TYPE);
TextBox<?,?> box1 = slide.createTextBox();
box1.setTextPlaceholder(TextPlaceholder.TITLE);
box1.setText("HSLF in Action - 2");
box1.setAnchor(new Rectangle(36, 20, 648, 90));
slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox();
TextBox<?,?> box2 = slide.createTextBox();
box2.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(18d);
box2.setText("Creating a simple presentation from scratch");
box2.setAnchor(new Rectangle(170, 100, 364, 30));
slide.addShape(box2);
HSLFTextBox box3 = new HSLFTextBox();
HSLFTextRun rt3 = box3.getTextParagraphs().get(0).getTextRuns().get(0);
TextBox<?,?> box3 = slide.createTextBox();
TextRun rt3 = box3.getTextParagraphs().get(0).getTextRuns().get(0);
rt3.setFontFamily("Courier New");
rt3.setFontSize(8d);
box3.setText(
@ -283,77 +264,67 @@ public final class ApacheconEU08 {
"out.close();");
box3.setAnchor(new Rectangle(30, 150, 618, 411));
box3.setHorizontalCentered(true);
slide.addShape(box3);
}
public static void slide7(HSLFSlideShow ppt) throws IOException {
HSLFSlide slide = ppt.createSlide();
public static void slide7(SlideShow<?,?> ppt) throws IOException {
Slide<?,?> slide = ppt.createSlide();
HSLFTextBox box2 = new HSLFTextBox();
TextBox<?,?> box2 = slide.createTextBox();
box2.setHorizontalCentered(true);
box2.setVerticalAlignment(VerticalAlignment.MIDDLE);
box2.setText("Java Code");
box2.getFill().setForegroundColor(new Color(187, 224, 227));
box2.setLineColor(Color.black);
box2.setLineWidth(0.75);
box2.setFillColor(new Color(187, 224, 227));
box2.setStrokeStyle(0.75, Color.black);
box2.setAnchor(new Rectangle(66, 243, 170, 170));
slide.addShape(box2);
HSLFTextBox box3 = new HSLFTextBox();
TextBox<?,?> box3 = slide.createTextBox();
box3.setHorizontalCentered(true);
box3.setVerticalAlignment(VerticalAlignment.MIDDLE);
box3.setText("*.ppt file");
box3.setLineWidth(0.75);
box3.setLineColor(Color.black);
box3.getFill().setForegroundColor(new Color(187, 224, 227));
box3.setFillColor(new Color(187, 224, 227));
box3.setStrokeStyle(0.75, Color.black);
box3.setAnchor(new Rectangle(473, 243, 170, 170));
slide.addShape(box3);
HSLFAutoShape box4 = new HSLFAutoShape(ShapeType.RIGHT_ARROW);
box4.getFill().setForegroundColor(new Color(187, 224, 227));
box4.setLineWidth(0.75);
box4.setLineColor(Color.black);
AutoShape<?,?> box4 = slide.createAutoShape();
box4.setShapeType(ShapeType.RIGHT_ARROW);
box4.setFillColor(new Color(187, 224, 227));
box4.setStrokeStyle(0.75, Color.black);
box4.setAnchor(new Rectangle(253, 288, 198, 85));
slide.addShape(box4);
}
public static void slide8(HSLFSlideShow ppt) throws IOException {
HSLFSlide slide = ppt.createSlide();
public static void slide8(SlideShow<?,?> ppt) throws IOException {
Slide<?,?> slide = ppt.createSlide();
HSLFTextBox box1 = new HSLFTextBox();
box1.setRunType(TextHeaderAtom.TITLE_TYPE);
TextBox<?,?> box1 = slide.createTextBox();
box1.setTextPlaceholder(TextPlaceholder.TITLE);
box1.setText("Wait, there is more!");
box1.setAnchor(new Rectangle(36, 21, 648, 90));
slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox();
box2.setRunType(TextHeaderAtom.BODY_TYPE);
TextBox<?,?> box2 = slide.createTextBox();
box2.setTextPlaceholder(TextPlaceholder.BODY);
box2.setText(
"Rich text\r" +
"Tables\r" +
"Pictures (JPEG, PNG, BMP, WMF, PICT)\r" +
"Comprehensive formatting features");
box2.setAnchor(new Rectangle(36, 126, 648, 356));
slide.addShape(box2);
}
public static void slide9(HSLFSlideShow ppt) throws IOException {
HSLFSlide slide = ppt.createSlide();
public static void slide9(SlideShow<?,?> ppt) throws IOException {
Slide<?,?> slide = ppt.createSlide();
HSLFTextBox box1 = new HSLFTextBox();
box1.setRunType(TextHeaderAtom.TITLE_TYPE);
TextBox<?,?> box1 = slide.createTextBox();
box1.setTextPlaceholder(TextPlaceholder.TITLE);
box1.setText("HSLF in Action - 3");
box1.setAnchor(new Rectangle(36, 20, 648, 50));
slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox();
TextBox<?,?> box2 = slide.createTextBox();
box2.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(18d);
box2.setText("PPGraphics2D: PowerPoint Graphics2D driver");
box2.setAnchor(new Rectangle(178, 70, 387, 30));
slide.addShape(box2);
HSLFTextBox box3 = new HSLFTextBox();
HSLFTextRun rt3 = box3.getTextParagraphs().get(0).getTextRuns().get(0);
TextBox<?,?> box3 = slide.createTextBox();
TextRun rt3 = box3.getTextParagraphs().get(0).getTextRuns().get(0);
rt3.setFontFamily("Courier New");
rt3.setFontSize(8d);
box3.setText(
@ -397,10 +368,9 @@ public final class ApacheconEU08 {
"out.close();");
box3.setAnchor(new Rectangle(96, 110, 499, 378));
box3.setHorizontalCentered(true);
slide.addShape(box3);
}
public static void slide10(HSLFSlideShow ppt) throws IOException {
public static void slide10(SlideShow<?,?> ppt) throws IOException {
//bar chart data. The first value is the bar color, the second is the width
Object[] def = new Object[]{
Color.yellow, new Integer(100),
@ -409,14 +379,13 @@ public final class ApacheconEU08 {
Color.red, new Integer(200),
};
HSLFSlide slide = ppt.createSlide();
Slide<?,?> slide = ppt.createSlide();
HSLFGroupShape group = new HSLFGroupShape();
GroupShape<?,?> group = slide.createGroup();
//define position of the drawing in the slide
Rectangle bounds = new java.awt.Rectangle(200, 100, 350, 300);
group.setAnchor(bounds);
slide.addShape(group);
Graphics2D graphics = new PPGraphics2D(group);
Graphics2D graphics = new SLGraphics(group);
//draw a simple bar graph
int x = bounds.x + 50, y = bounds.y + 50;
@ -437,17 +406,16 @@ public final class ApacheconEU08 {
}
public static void slide11(HSLFSlideShow ppt) throws IOException {
HSLFSlide slide = ppt.createSlide();
public static void slide11(SlideShow<?,?> ppt) throws IOException {
Slide<?,?> slide = ppt.createSlide();
HSLFTextBox box1 = new HSLFTextBox();
box1.setRunType(TextHeaderAtom.TITLE_TYPE);
TextBox<?,?> box1 = slide.createTextBox();
box1.setTextPlaceholder(TextPlaceholder.TITLE);
box1.setText("HSLF Development Plans");
box1.setAnchor(new Rectangle(36, 21, 648, 90));
slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox();
box2.setRunType(TextHeaderAtom.BODY_TYPE);
TextBox<?,?> box2 = slide.createTextBox();
box2.setTextPlaceholder(TextPlaceholder.BODY);
box2.setText(
"Support for more PowerPoint functionality\r" +
"Rendering slides into java.awt.Graphics2D\r" +
@ -457,7 +425,7 @@ public final class ApacheconEU08 {
"PPT2PDF transcoder"
);
List<HSLFTextParagraph> tp = box2.getTextParagraphs();
List<? extends TextParagraph<?,?,?>> tp = box2.getTextParagraphs();
for (int i : new byte[]{0,1,3}) {
tp.get(i).getTextRuns().get(0).setFontSize(28d);
}
@ -467,24 +435,21 @@ public final class ApacheconEU08 {
}
box2.setAnchor(new Rectangle(36, 126, 648, 400));
slide.addShape(box2);
}
public static void slide12(HSLFSlideShow ppt) throws IOException {
HSLFSlide slide = ppt.createSlide();
public static void slide12(SlideShow<?,?> ppt) throws IOException {
Slide<?,?> slide = ppt.createSlide();
HSLFTextBox box1 = new HSLFTextBox();
box1.setRunType(TextHeaderAtom.CENTER_TITLE_TYPE);
TextBox<?,?> box1 = slide.createTextBox();
box1.setTextPlaceholder(TextPlaceholder.CENTER_TITLE);
box1.setText("Questions?");
box1.setAnchor(new Rectangle(54, 167, 612, 115));
slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox();
box2.setRunType(TextHeaderAtom.CENTRE_BODY_TYPE);
TextBox<?,?> box2 = slide.createTextBox();
box2.setTextPlaceholder(TextPlaceholder.CENTER_BODY);
box2.setText(
"http://poi.apache.org/hslf/\r" +
"http://people.apache.org/~yegor");
box2.setAnchor(new Rectangle(108, 306, 504, 138));
slide.addShape(box2);
}
}

View File

@ -25,7 +25,7 @@ import org.apache.poi.hslf.usermodel.HSLFSlideShow;
import org.apache.poi.hslf.usermodel.HSLFTable;
import org.apache.poi.hslf.usermodel.HSLFTableCell;
import org.apache.poi.hslf.usermodel.HSLFTextRun;
import org.apache.poi.hslf.usermodel.HSLFLine;
import org.apache.poi.sl.draw.DrawTableShape;
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
import org.apache.poi.sl.usermodel.VerticalAlignment;
@ -53,7 +53,7 @@ public final class TableDemo {
HSLFSlide slide = ppt.createSlide();
//six rows, two columns
HSLFTable table1 = new HSLFTable(6, 2);
HSLFTable table1 = slide.createTable(6, 2);
for (int i = 0; i < txt1.length; i++) {
for (int j = 0; j < txt1[i].length; j++) {
HSLFTableCell cell = table1.getCell(i, j);
@ -71,15 +71,12 @@ public final class TableDemo {
}
}
HSLFLine border1 = table1.createBorder();
border1.setLineColor(Color.black);
border1.setLineWidth(1.0);
table1.setAllBorders(border1);
DrawTableShape dts1 = new DrawTableShape(table1);
dts1.setAllBorders(1.0, Color.black);
table1.setColumnWidth(0, 300);
table1.setColumnWidth(1, 150);
slide.addShape(table1);
int pgWidth = ppt.getPageSize().width;
table1.moveTo((pgWidth - table1.getAnchor().width)/2, 100);
@ -92,7 +89,7 @@ public final class TableDemo {
};
//two rows, one column
HSLFTable table2 = new HSLFTable(2, 1);
HSLFTable table2 = slide.createTable(2, 1);
for (int i = 0; i < txt2.length; i++) {
for (int j = 0; j < txt2[i].length; j++) {
HSLFTableCell cell = table2.getCell(i, j);
@ -119,10 +116,9 @@ public final class TableDemo {
table2.setRowHeight(0, 30);
table2.setRowHeight(1, 70);
HSLFLine border2 = table2.createBorder();
table2.setOutsideBorders(border2);
DrawTableShape dts2 = new DrawTableShape(table2);
dts2.setOutsideBorders(Color.black, 1.0);
slide.addShape(table2);
table2.moveTo(200, 400);
FileOutputStream out = new FileOutputStream("hslf-table.ppt");

View File

@ -23,6 +23,8 @@ import java.awt.Rectangle;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
/**
* How to set slide title
*

View File

@ -24,6 +24,7 @@ import java.awt.Rectangle;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.sl.usermodel.TableCell.BorderEdge;
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
/**
@ -56,8 +57,8 @@ public class Tutorial4 {
r.setBold(true);
r.setFontColor(Color.white);
th.setFillColor(new Color(79, 129, 189));
th.setBorderBottom(2);
th.setBorderBottomColor(Color.white);
th.setBorderWidth(BorderEdge.bottom, 2.0);
th.setBorderColor(BorderEdge.bottom, Color.white);
tbl.setColumnWidth(i, 150); // all columns are equally sized
}

View File

@ -17,9 +17,15 @@
package org.apache.poi.sl.draw;
import java.awt.Color;
import java.awt.Graphics2D;
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.LineDash;
import org.apache.poi.sl.usermodel.TableCell;
import org.apache.poi.sl.usermodel.TableCell.BorderEdge;
import org.apache.poi.sl.usermodel.TableShape;
public class DrawTableShape extends DrawShape {
@ -57,5 +63,111 @@ public class DrawTableShape extends DrawShape {
}
}
@Override
protected TableShape<?,?> getShape() {
return (TableShape<?,?>)shape;
}
/**
* Format the table and apply the specified Line to all cell boundaries,
* both outside and inside.
* An empty args parameter removes the affected border.
*
* @param args a varargs array possible containing {@link Double} (width),
* {@link StrokeStyle.LineCompound}, {@link Color}, {@link StrokeStyle.LineDash}
*/
public void setAllBorders(Object... args) {
TableShape<?,?> table = getShape();
final int rows = table.getNumberOfRows();
final int cols = table.getNumberOfColumns();
BorderEdge edges[] = { BorderEdge.top, BorderEdge.left, null, null };
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
edges[2] = (col == cols - 1) ? BorderEdge.right : null;
edges[3] = (row == rows - 1) ? BorderEdge.bottom : null;
setEdges(table.getCell(row, col), edges, args);
}
}
}
/**
* Format the outside border using the specified Line object
* An empty args parameter removes the affected border.
*
* @param args a varargs array possible containing {@link Double} (width),
* {@link StrokeStyle.LineCompound}, {@link Color}, {@link StrokeStyle.LineDash}
*/
public void setOutsideBorders(Object... args){
if (args.length == 0) return;
TableShape<?,?> table = getShape();
final int rows = table.getNumberOfRows();
final int cols = table.getNumberOfColumns();
BorderEdge edges[] = new BorderEdge[4];
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
edges[0] = (col == 0) ? BorderEdge.left : null;
edges[1] = (col == cols - 1) ? BorderEdge.right : null;
edges[2] = (row == 0) ? BorderEdge.top : null;
edges[3] = (row == rows - 1) ? BorderEdge.bottom : null;
setEdges(table.getCell(row, col), edges, args);
}
}
}
/**
* Format the inside border using the specified Line object
* An empty args parameter removes the affected border.
*
* @param args a varargs array possible containing {@link Double} (width),
* {@link StrokeStyle.LineCompound}, {@link Color}, {@link StrokeStyle.LineDash}
*/
public void setInsideBorders(Object... args) {
if (args.length == 0) return;
TableShape<?,?> table = getShape();
final int rows = table.getNumberOfRows();
final int cols = table.getNumberOfColumns();
BorderEdge edges[] = new BorderEdge[2];
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
edges[0] = (col > 0 && col < cols - 1) ? BorderEdge.right : null;
edges[1] = (row > 0 && row < rows - 1) ? BorderEdge.bottom : null;
setEdges(table.getCell(row, col), edges, args);
}
}
}
/**
* Apply the border attributes (args) to the given cell and edges
*
* @param cell the cell
* @param edges the border edges
* @param args the border attributes
*/
private static void setEdges(TableCell<?,?> cell, BorderEdge edges[], Object... args) {
for (BorderEdge be : edges) {
if (be != null) {
if (args.length == 0) {
cell.removeBorder(be);
} else {
for (Object o : args) {
if (o instanceof Double) {
cell.setBorderWidth(be, (Double)o);
} else if (o instanceof Color) {
cell.setBorderColor(be, (Color)o);
} else if (o instanceof LineDash) {
cell.setBorderDash(be, (LineDash)o);
} else if (o instanceof LineCompound) {
cell.setBorderCompound(be, (LineCompound)o);
}
}
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,8 @@
package org.apache.poi.sl.usermodel;
import java.awt.Color;
import org.apache.poi.sl.draw.geom.CustomGeometry;
import org.apache.poi.sl.draw.geom.IAdjustableShape;
@ -25,15 +27,66 @@ public interface SimpleShape<
S extends Shape<S,P>,
P extends TextParagraph<S,P,?>
> extends Shape<S,P>, IAdjustableShape, PlaceableShape<S,P> {
enum Placeholder {
TITLE,
BODY,
CENTERED_TITLE,
SUBTITLE,
DATETIME,
SLIDE_NUMBER,
FOOTER,
HEADER,
CONTENT,
CHART,
TABLE,
CLIP_ART,
DGM,
MEDIA,
SLIDE_IMAGE,
PICTURE
}
FillStyle getFillStyle();
LineDecoration getLineDecoration();
StrokeStyle getStrokeStyle();
/**
* Sets the line attributes.
* Possible attributes are Double (width), LineCap, LineDash, LineCompound, Color
* (implementations of PaintStyle aren't yet supported ...)
*
* If no styles are given, the line will be hidden
*
* @param styles the line attributes
*/
void setStrokeStyle(Object... styles);
CustomGeometry getGeometry();
ShapeType getShapeType();
void setShapeType(ShapeType type);
boolean isPlaceholder();
Shadow<S,P> getShadow();
/**
* Returns the solid color fill.
*
* @return solid fill color of null if not set or fill color
* is not solid (pattern or gradient)
*/
Color getFillColor();
/**
* Specifies a solid color fill. The shape is filled entirely with the
* specified color.
*
* @param color the solid color fill. The value of <code>null</code> unsets
* the solid fill attribute from the underlying implementation
*/
void setFillColor(Color color);
}

View File

@ -49,6 +49,13 @@ public interface SlideShow<
*/
Dimension getPageSize();
/**
* Change the current page size
*
* @param pgsize page size (in points)
*/
void setPageSize(Dimension pgsize);
/**
* Returns all Pictures of this slideshow.
* The returned {@link List} is unmodifiable.

View File

@ -20,18 +20,27 @@ package org.apache.poi.sl.usermodel;
public interface StrokeStyle {
enum LineCap {
/** Rounded ends */
ROUND(1),
ROUND(0,1),
/** Square protrudes by half line width */
SQUARE(2),
SQUARE(1,2),
/** Line ends at end point*/
FLAT(3);
FLAT(2,3);
public final int nativeId;
public final int ooxmlId;
LineCap(int ooxmlId) {
LineCap(int nativeId, int ooxmlId) {
this.nativeId = nativeId;
this.ooxmlId = ooxmlId;
}
public static LineCap fromNativeId(int nativeId) {
for (LineCap ld : values()) {
if (ld.nativeId == nativeId) return ld;
}
return null;
}
public static LineCap fromOoxmlId(int ooxmlId) {
for (LineCap lc : values()) {
if (lc.ooxmlId == ooxmlId) return lc;
@ -96,20 +105,22 @@ public interface StrokeStyle {
enum LineCompound {
/** Single line (of width lineWidth) - native 0 / ooxml default */
SINGLE(0),
SINGLE(0, 1),
/** Double lines of equal width - native 1 / ooxml "dbl" */
DOUBLE(1),
DOUBLE(1, 2),
/** Double lines, one thick, one thin - native 2 / ooxml "thickThin" */
THICK_THIN(2),
THICK_THIN(2, 3),
/** Double lines, reverse order - native 3 / ooxml "thinThick" */
THIN_THICK(3),
THIN_THICK(3, 4),
/** Three lines, thin, thick, thin - native 4 / ooxml "tri" */
TRIPLE(4);
TRIPLE(4, 5);
public final int nativeId;
public final int ooxmlId;
LineCompound(int nativeId) {
LineCompound(int nativeId, int ooxmlId) {
this.nativeId = nativeId;
this.ooxmlId = ooxmlId;
}
public static LineCompound fromNativeId(int nativeId) {
@ -118,6 +129,13 @@ public interface StrokeStyle {
}
return null;
}
public static LineCompound fromOoxmlId(int ooxmlId) {
for (LineCompound lc : values()) {
if (lc.ooxmlId == ooxmlId) return lc;
}
return null;
}
}

View File

@ -17,9 +17,70 @@
package org.apache.poi.sl.usermodel;
import java.awt.Color;
import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
public interface TableCell<
S extends Shape<S,P>,
P extends TextParagraph<S,P,?>
> extends TextShape<S,P> {
enum BorderEdge { bottom, left, top, right };
/**
* Return line style of given edge or {@code null} if border is not defined
*
* @param edge the border edge
* @return line style of given edge or {@code null} if border is not defined
*/
StrokeStyle getBorderStyle(BorderEdge edge);
/**
* Sets the {@link StrokeStyle} of the given border edge.
* A {@code null} property of the style is ignored.
*
* @param edge border edge
* @param style the new stroke style
*/
void setBorderStyle(BorderEdge edge, StrokeStyle style);
/**
* Convenience method for setting the border width.
*
* @param edge border edge
* @param width the new border width
*/
void setBorderWidth(BorderEdge edge, double width);
/**
* Convenience method for setting the border color.
*
* @param edge border edge
* @param color the new border color
*/
void setBorderColor(BorderEdge edge, Color color);
/**
* Convenience method for setting the border line compound.
*
* @param edge border edge
* @param compound the new border line compound
*/
void setBorderCompound(BorderEdge edge, LineCompound compound);
/**
* Convenience method for setting the border line dash.
*
* @param edge border edge
* @param dash the new border line dash
*/
void setBorderDash(BorderEdge edge, LineDash dash);
/**
* Remove all line attributes of the given border edge
*
* @param edge the border edge to be cleared
*/
void removeBorder(BorderEdge edge);
}

View File

@ -21,5 +21,25 @@ public interface TableShape<
S extends Shape<S,P>,
P extends TextParagraph<S,P,?>
> extends Shape<S,P>, PlaceableShape<S,P> {
// to be defined ...
int getNumberOfColumns();
int getNumberOfRows();
TableCell<S,P> getCell(int row, int col);
/**
* Sets the width (in points) of the n-th column
*
* @param idx the column index (0-based)
* @param width the width (in points)
*/
void setColumnWidth(int idx, double width);
/**
* Sets the row height.
*
* @param row the row index (0-based)
* @param height the height to set (in points)
*/
void setRowHeight(int row, double height);
}

View File

@ -17,6 +17,13 @@
package org.apache.poi.sl.usermodel;
/**
* Represents a TextFrame shape in PowerPoint.
* <p>
* Contains the text in a text frame as well as the properties and methods
* that control alignment and anchoring of the text.
* </p>
*/
public interface TextBox<
S extends Shape<S,P>,
P extends TextParagraph<S,P,?>

View File

@ -18,6 +18,7 @@
package org.apache.poi.sl.usermodel;
import java.awt.Color;
import java.util.List;
@ -339,4 +340,9 @@ public interface TextParagraph<
TextShape<S,P> getParentShape();
/**
* Fetch the text runs that are contained within this block of text
*/
List<T> getTextRuns();
}

View File

@ -32,21 +32,21 @@ public interface TextRun {
}
String getRawText();
void setText(String text);
void setText(String text);
TextCap getTextCap();
TextCap getTextCap();
/**
* Returns the font color.
* This usually returns a {@link SolidPaint}, but but also other classes are possible
*
* @return the font color/paint
*
/**
* Returns the font color.
* This usually returns a {@link SolidPaint}, but but also other classes are possible
*
* @return the font color/paint
*
* @see org.apache.poi.sl.draw.DrawPaint#getPaint(java.awt.Graphics2D, PaintStyle)
* @see SolidPaint#getSolidColor()
* @see org.apache.poi.sl.draw.DrawPaint#applyColorTransform(ColorStyle)
*/
PaintStyle getFontColor();
* @see org.apache.poi.sl.draw.DrawPaint#applyColorTransform(ColorStyle)
*/
PaintStyle getFontColor();
/**
* Sets the (solid) font color - convenience function
@ -56,13 +56,13 @@ public interface TextRun {
void setFontColor(Color color);
/**
* Sets the font color
*
* @param color the color
*
* @see org.apache.poi.sl.draw.DrawPaint#createSolidPaint(Color)
*/
void setFontColor(PaintStyle color);
* Sets the font color
*
* @param color the color
*
* @see org.apache.poi.sl.draw.DrawPaint#createSolidPaint(Color)
*/
void setFontColor(PaintStyle color);
/**
@ -71,7 +71,7 @@ public interface TextRun {
*
* @return font size in points or null if font size is not set.
*/
Double getFontSize();
Double getFontSize();
/**
* Sets the font size directly on this text run, if null is given, the
@ -79,18 +79,81 @@ public interface TextRun {
*
* @param fontSize font size in points, if null the underlying fontsize will be unset
*/
void setFontSize(Double fontSize);
String getFontFamily();
void setFontSize(Double fontSize);
boolean isBold();
boolean isItalic();
boolean isUnderlined();
boolean isStrikethrough();
boolean isSubscript();
boolean isSuperscript();
/**
* @return font family or null if not set
*/
String getFontFamily();
/**
* @return the pitch and family id or -1 if not applicable
*/
byte getPitchAndFamily();
/**
* Specifies the typeface, or name of the font that is to be used for this text run.
*
* @param typeface the font to apply to this text run.
* The value of <code>null</code> unsets the Typeface attrubute from the underlying xml.
*/
void setFontFamily(String typeface);
/**
* @return true, if text is bold
*/
boolean isBold();
/**
* Sets the bold state
*
* @param bold set to true for bold text, false for normal weight
*/
void setBold(boolean bold);
/**
* @return true, if text is italic
*/
boolean isItalic();
/**
* Sets the italic state
*
* @param italic set to true for italic text, false for non-italics
*/
void setItalic(boolean italic);
/**
* @return true, if text is underlined
*/
boolean isUnderlined();
/**
* Sets the underlined state
*
* @param underlined set to true for underlined text, false for no underlining
*/
void setUnderlined(boolean underlined);
/**
* @return true, if text is stroked
*/
boolean isStrikethrough();
/**
* Sets the strikethrough state
*
* @param stroked set to true for stroked text, false for no stroking
*/
void setStrikethrough(boolean stroked);
/**
* @return true, if text is sub scripted
*/
boolean isSubscript();
/**
* @return true, if text is super scripted
*/
boolean isSuperscript();
/**
* @return the pitch and family id or -1 if not applicable
*/
byte getPitchAndFamily();
}

View File

@ -26,7 +26,7 @@ public interface TextShape<
/**
* Vertical Text Types
*/
public enum TextDirection {
enum TextDirection {
/**
* Horizontal text. This should be default.
*/
@ -59,7 +59,7 @@ public interface TextShape<
* Auto-fitting is when text within a shape is scaled in order to contain all the text inside
* </p>
*/
public enum TextAutofit {
enum TextAutofit {
/**
* Specifies that text within the text body should not be auto-fit to the bounding box.
* Auto-fitting is when text within a text box is scaled in order to remain inside
@ -90,6 +90,46 @@ public interface TextShape<
SHAPE
}
/**
* This enum represents a compromise for the handling of
* HSLF run types (see org.apache.poi.hslf.record.TextHeaderAtom) and
* XSLF placeholders (see org.apache.poi.xslf.usermodel.Placeholder).
* When a shape is considered a placeholder by the generating application
* it can have special properties to alert the user that they may enter content into the shape.
*
* This enum and the handling around it may change significantly in future releases
*/
enum TextPlaceholder {
/** Title placeholder shape text */
TITLE,
/** Body placeholder shape text */
BODY,
/** Center title placeholder shape text */
CENTER_TITLE,
/** Center body placeholder shape text */
CENTER_BODY,
/** Half-sized body placeholder shape text */
HALF_BODY,
/** Quarter-sized body placeholder shape text */
QUARTER_BODY,
/** Notes placeholder shape text */
NOTES,
/** Any other text */
OTHER
}
/**
* Sets (overwrites) the current text.
* Uses the properties of the first paragraph / textrun.
* Text paragraphs are split by \\r or \\n.
* New lines within text run are split by \\u000b
*
* @param text the text string used by this object.
*
* @return the last text run of the - potential split - text
*/
TextRun setText(String text);
/**
* @return the TextParagraphs for this text box
*/
@ -100,6 +140,13 @@ public interface TextShape<
*/
Insets2D getInsets();
/**
* Sets the shape margins
*
* @param insets the new shape margins
*/
void setInsets(Insets2D insets);
/**
* Compute the cumulative height occupied by the text
*/
@ -112,6 +159,14 @@ public interface TextShape<
*/
VerticalAlignment getVerticalAlignment();
/**
* Sets the type of vertical alignment for the text.
*
* @param vAlign - the type of alignment.
* A {@code null} values unsets this property.
*/
void setVerticalAlignment(VerticalAlignment vAlign);
/**
* Returns if the text is centered.
* If true and if the individual paragraph settings allow it,
@ -122,13 +177,36 @@ public interface TextShape<
*/
boolean isHorizontalCentered();
/**
* Sets if the paragraphs are horizontal centered
*
* @param isCentered true, if the paragraphs are horizontal centered
* A {@code null} values unsets this property.
*/
void setHorizontalCentered(Boolean isCentered);
/**
* @return whether to wrap words within the bounding rectangle
*/
boolean getWordWrap();
/**
* @param wrap whether to wrap words within the bounding rectangle
*/
void setWordWrap(boolean wrap);
/**
* @return vertical orientation of the text
*/
TextDirection getTextDirection();
/**
* Sets the text placeholder
*/
void setTextPlaceholder(TextPlaceholder placeholder);
/**
* @return the text placeholder
*/
TextPlaceholder getTextPlaceholder();
}

View File

@ -1,41 +0,0 @@
/*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.apache.poi.xslf.usermodel;
/**
* @author Yegor Kozlov
*/
public enum Placeholder {
TITLE,
BODY,
CENTERED_TITLE,
SUBTITLE,
DATETIME,
SLIDE_NUMBER,
FOOTER,
HEADER,
CONTENT,
CHART,
TABLE,
CLIP_ART,
DGM,
MEDIA,
SLIDE_IMAGE,
PICTURE
}

View File

@ -41,7 +41,6 @@ import org.apache.poi.sl.usermodel.PictureData.PictureType;
import org.apache.poi.sl.usermodel.Resources;
import org.apache.poi.sl.usermodel.SlideShow;
import org.apache.poi.util.Beta;
import org.apache.poi.util.DocumentHelper;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian;
@ -404,11 +403,7 @@ implements SlideShow<XSLFShape,XSLFTextParagraph> {
return slide;
}
/**
* Returns the current page size
*
* @return the page size
*/
@Override
public Dimension getPageSize(){
CTSlideSize sz = _presentation.getSldSz();
int cx = sz.getCx();
@ -416,11 +411,7 @@ implements SlideShow<XSLFShape,XSLFTextParagraph> {
return new Dimension((int)Units.toPoints(cx), (int)Units.toPoints(cy));
}
/**
* Sets the page size to the given <code>Dimension</code> object.
*
* @param pgSize page size
*/
@Override
public void setPageSize(Dimension pgSize){
CTSlideSize sz = CTSlideSize.Factory.newInstance();
sz.setCx(Units.toEMU(pgSize.getWidth()));

View File

@ -25,7 +25,12 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual;
@ -72,13 +77,25 @@ public class XSLFAutoShape extends XSLFTextShape
return ct;
}
protected static void initTextBody(CTTextBody txBody) {
CTTextBodyProperties bodypr = txBody.addNewBodyPr();
bodypr.setAnchor(STTextAnchoringType.T);
bodypr.setRtlCol(false);
CTTextParagraph p = txBody.addNewP();
p.addNewPPr().setAlgn(STTextAlignType.L);
CTTextCharacterProperties endPr = p.addNewEndParaRPr();
endPr.setLang("en-US");
endPr.setSz(1100);
p.addNewR().setT("");
txBody.addNewLstStyle();
}
protected CTTextBody getTextBody(boolean create){
CTShape shape = (CTShape)getXmlObject();
CTTextBody txBody = shape.getTxBody();
if (txBody == null && create) {
txBody = shape.addNewTxBody();
txBody.addNewBodyPr();
txBody.addNewLstStyle();
initTextBody(txBody);
}
return txBody;
}

View File

@ -33,6 +33,7 @@ import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint;
import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;
import org.apache.poi.sl.usermodel.PlaceableShape;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.sl.usermodel.Shape;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;

View File

@ -39,6 +39,7 @@ import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.draw.DrawPictureShape;
import org.apache.poi.sl.draw.Drawable;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.sl.usermodel.Sheet;
import org.apache.poi.util.Beta;
import org.apache.poi.util.IOUtils;

View File

@ -88,15 +88,13 @@ public abstract class XSLFSimpleShape extends XSLFShape
super(shape,sheet);
}
/**
*
* @param type
*/
public void setShapeType(ShapeType type){
@Override
public void setShapeType(ShapeType type) {
STShapeType.Enum geom = STShapeType.Enum.forInt(type.ooxmlId);
getSpPr().getPrstGeom().setPrst(geom);
}
@Override
public ShapeType getShapeType(){
STShapeType.Enum geom = getSpPr().getPrstGeom().getPrst();
return ShapeType.forId(geom.intValue(), true);
@ -362,6 +360,40 @@ public abstract class XSLFSimpleShape extends XSLFShape
return lineWidth;
}
/**
* @param compound set the line compound style
*/
public void setLineCompound(LineCompound compound) {
CTShapeProperties spPr = getSpPr();
if (compound == null) {
if (spPr.isSetLn() && spPr.getLn().isSetCmpd())
spPr.getLn().unsetCmpd();
} else {
CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr.addNewLn();
STCompoundLine.Enum xCmpd;
switch (compound) {
default:
case SINGLE:
xCmpd = STCompoundLine.SNG;
break;
case DOUBLE:
xCmpd = STCompoundLine.DBL;
break;
case THICK_THIN:
xCmpd = STCompoundLine.THICK_THIN;
break;
case THIN_THICK:
xCmpd = STCompoundLine.THIN_THICK;
break;
case TRIPLE:
xCmpd = STCompoundLine.TRI;
break;
}
ln.setCmpd(xCmpd);
}
}
/**
* @return the line compound
*/
@ -417,15 +449,12 @@ public abstract class XSLFSimpleShape extends XSLFShape
public void setLineDash(LineDash dash) {
CTShapeProperties spPr = getSpPr();
if (dash == null) {
if (spPr.isSetLn() && spPr.getLn().isSetPrstDash())
if (spPr.isSetLn() && spPr.getLn().isSetPrstDash())
spPr.getLn().unsetPrstDash();
} else {
CTPresetLineDashProperties val = CTPresetLineDashProperties.Factory
.newInstance();
val.setVal(STPresetLineDashVal.Enum.forInt(dash.ooxmlId));
CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr
.addNewLn();
ln.setPrstDash(val);
CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr.addNewLn();
CTPresetLineDashProperties ldp = ln.isSetPrstDash() ? ln.getPrstDash() : ln.addNewPrstDash();
ldp.setVal(STPresetLineDashVal.Enum.forInt(dash.ooxmlId));
}
}
@ -513,13 +542,7 @@ public abstract class XSLFSimpleShape extends XSLFShape
return cap;
}
/**
* Specifies a solid color fill. The shape is filled entirely with the
* specified color.
*
* @param color the solid color fill. The value of <code>null</code> unsets
* the solidFIll attribute from the underlying xml
*/
@Override
public void setFillColor(Color color) {
CTShapeProperties spPr = getSpPr();
if (color == null) {
@ -545,10 +568,7 @@ public abstract class XSLFSimpleShape extends XSLFShape
}
}
/**
* @return solid fill color of null if not set or fill color
* is not solid (pattern or gradient)
*/
@Override
public Color getFillColor() {
PaintStyle ps = getFillPaint();
if (ps instanceof SolidPaint) {
@ -874,4 +894,28 @@ public abstract class XSLFSimpleShape extends XSLFShape
};
}
@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);
}
}
}
}

View File

@ -25,9 +25,9 @@ import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.draw.Drawable;
import org.apache.poi.sl.usermodel.Notes;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.sl.usermodel.Slide;
import org.apache.poi.util.Beta;
import org.apache.poi.util.DocumentHelper;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupShapeProperties;

View File

@ -22,8 +22,8 @@ import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.sl.usermodel.MasterSheet;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.util.Beta;
import org.apache.poi.util.DocumentHelper;
import org.apache.poi.util.Internal;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground;

View File

@ -25,8 +25,8 @@ import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.sl.usermodel.MasterSheet;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.util.Beta;
import org.apache.poi.util.DocumentHelper;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColorMapping;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextListStyle;

View File

@ -80,15 +80,22 @@ public class XSLFTable extends XSLFGraphicFrame implements Iterable<XSLFTableRow
for(CTTableRow row : trArray) _rows.add(new XSLFTableRow(row, this));
}
@Override
public XSLFTableCell getCell(int row, int col) {
return getRows().get(row).getCells().get(col);
}
@Internal
public CTTable getCTTable(){
return _table;
}
@Override
public int getNumberOfColumns() {
return _table.getTblGrid().sizeOfGridColArray();
}
@Override
public int getNumberOfRows() {
return _table.sizeOfTrArray();
}
@ -98,10 +105,16 @@ public class XSLFTable extends XSLFGraphicFrame implements Iterable<XSLFTableRow
_table.getTblGrid().getGridColArray(idx).getW());
}
public void setColumnWidth(int idx, double width){
@Override
public void setColumnWidth(int idx, double width) {
_table.getTblGrid().getGridColArray(idx).setW(Units.toEMU(width));
}
@Override
public void setRowHeight(int row, double height) {
_table.getTrArray(row).setH(Units.toEMU(height));
}
public Iterator<XSLFTableRow> iterator(){
return _rows.iterator();
}

View File

@ -21,6 +21,12 @@ package org.apache.poi.xslf.usermodel;
import java.awt.Color;
import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.StrokeStyle;
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.sl.usermodel.TableCell;
import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.util.Units;
@ -44,7 +50,6 @@ import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType;
* Represents a cell of a table in a .pptx presentation
*/
public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,XSLFTextParagraph> {
static double defaultBorderWidth = 1.0;
private CTTableCellProperties _tcPr = null;
/*package*/ XSLFTableCell(CTTableCell cell, XSLFSheet sheet){
@ -57,8 +62,7 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
CTTextBody txBody = cell.getTxBody();
if (txBody == null && create) {
txBody = cell.addNewTxBody();
txBody.addNewBodyPr();
txBody.addNewLstStyle();
XSLFAutoShape.initTextBody(txBody);
}
return txBody;
}
@ -108,67 +112,174 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
pr.setMarB(Units.toEMU(margin));
}
private CTLineProperties getCTLine(char bltr, boolean create) {
private CTLineProperties getCTLine(BorderEdge edge, boolean create) {
if (edge == null) {
throw new IllegalArgumentException("BorderEdge needs to be specified.");
}
CTTableCellProperties pr = getCellProperties(create);
if (pr == null) return null;
switch (bltr) {
case 'b':
switch (edge) {
case bottom:
return (pr.isSetLnB()) ? pr.getLnB() : (create ? pr.addNewLnB() : null);
case 'l':
case left:
return (pr.isSetLnL()) ? pr.getLnL() : (create ? pr.addNewLnL() : null);
case 't':
case top:
return (pr.isSetLnT()) ? pr.getLnT() : (create ? pr.addNewLnT() : null);
case 'r':
case right:
return (pr.isSetLnR()) ? pr.getLnR() : (create ? pr.addNewLnR() : null);
default:
return null;
}
}
private void setBorderWidth(char bltr, double width) {
CTLineProperties ln = getCTLine(bltr, true);
@Override
public void removeBorder(BorderEdge edge) {
CTTableCellProperties pr = getCellProperties(false);
if (pr == null) return;
switch (edge) {
case bottom:
if (pr.isSetLnB()) {
pr.unsetLnB();
}
break;
case left:
if (pr.isSetLnL()) {
pr.unsetLnL();
}
break;
case top:
if (pr.isSetLnT()) {
pr.unsetLnT();
}
break;
case right:
if (pr.isSetLnR()) {
pr.unsetLnB();
}
break;
default:
throw new IllegalArgumentException();
}
}
@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 getBorderCap(edge);
}
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.");
}
LineCap cap = style.getLineCap();
if (cap != null) {
setBorderCap(edge, cap);
}
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 Double getBorderWidth(BorderEdge edge) {
CTLineProperties ln = getCTLine(edge, false);
return (ln == null || !ln.isSetW()) ? null : Units.toPoints(ln.getW());
}
@Override
public void setBorderWidth(BorderEdge edge, double width) {
CTLineProperties ln = getCTLine(edge, true);
ln.setW(Units.toEMU(width));
}
private double getBorderWidth(char bltr) {
CTLineProperties ln = getCTLine(bltr, false);
return (ln == null || !ln.isSetW()) ? defaultBorderWidth : Units.toPoints(ln.getW());
}
private CTLineProperties setBorderDefaults(BorderEdge edge) {
CTLineProperties ln = getCTLine(edge, true);
if (ln.isSetNoFill()) {
ln.unsetNoFill();
}
private void setBorderColor(char bltr, Color color) {
CTLineProperties ln = getCTLine(bltr, true);
if(color == null){
ln.addNewNoFill();
if(ln.isSetSolidFill()) ln.unsetSolidFill();
} else {
if(ln.isSetNoFill()) ln.unsetNoFill();
if(!ln.isSetPrstDash()) ln.addNewPrstDash().setVal(STPresetLineDashVal.SOLID);
if(!ln.isSetPrstDash()) {
ln.addNewPrstDash().setVal(STPresetLineDashVal.SOLID);
}
if (!ln.isSetCmpd()) {
ln.setCmpd(STCompoundLine.SNG);
}
if (!ln.isSetAlgn()) {
ln.setAlgn(STPenAlignment.CTR);
}
if (!ln.isSetCap()) {
ln.setCap(STLineCap.FLAT);
}
if (!ln.isSetRound()) {
ln.addNewRound();
}
if (!ln.isSetHeadEnd()) {
CTLineEndProperties hd = ln.addNewHeadEnd();
hd.setType(STLineEndType.NONE);
hd.setW(STLineEndWidth.MED);
hd.setLen(STLineEndLength.MED);
}
if (!ln.isSetTailEnd()) {
CTLineEndProperties tl = ln.addNewTailEnd();
tl.setType(STLineEndType.NONE);
tl.setW(STLineEndWidth.MED);
tl.setLen(STLineEndLength.MED);
CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();
rgb.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()});
ln.addNewSolidFill().setSrgbClr(rgb);
}
return ln;
}
private Color getBorderColor(char bltr) {
CTLineProperties ln = getCTLine(bltr,false);
@Override
public void setBorderColor(BorderEdge edge, Color color) {
if (color == null) {
throw new IllegalArgumentException("Colors need to be specified.");
}
CTLineProperties ln = setBorderDefaults(edge);
CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();
rgb.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()});
ln.addNewSolidFill().setSrgbClr(rgb);
}
public Color getBorderColor(BorderEdge edge) {
CTLineProperties ln = getCTLine(edge, false);
if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill()) return null;
CTSolidColorFillProperties fill = ln.getSolidFill();
@ -180,69 +291,63 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);
}
public void setBorderLeft(double width) {
setBorderWidth('l', width);
public LineCompound getBorderCompound(BorderEdge edge) {
CTLineProperties ln = getCTLine(edge, false);
if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill() || !ln.isSetCmpd()) {
return null;
}
return LineCompound.fromOoxmlId(ln.getCmpd().intValue());
}
public double getBorderLeft() {
return getBorderWidth('l');
@Override
public void setBorderCompound(BorderEdge edge, LineCompound compound) {
if (compound == null) {
throw new IllegalArgumentException("LineCompound need to be specified.");
}
CTLineProperties ln = setBorderDefaults(edge);
ln.setCmpd(STCompoundLine.Enum.forInt(compound.ooxmlId));
}
public void setBorderLeftColor(Color color) {
setBorderColor('l', color);
public LineDash getBorderDash(BorderEdge edge) {
CTLineProperties ln = getCTLine(edge, false);
if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill() || !ln.isSetPrstDash()) {
return null;
}
return LineDash.fromOoxmlId(ln.getPrstDash().getVal().intValue());
}
public Color getBorderLeftColor() {
return getBorderColor('l');
@Override
public void setBorderDash(BorderEdge edge, LineDash dash) {
if (dash == null) {
throw new IllegalArgumentException("LineDash need to be specified.");
}
CTLineProperties ln = setBorderDefaults(edge);
ln.getPrstDash().setVal(STPresetLineDashVal.Enum.forInt(dash.ooxmlId));
}
public void setBorderRight(double width) {
setBorderWidth('r', width);
public LineCap getBorderCap(BorderEdge edge) {
CTLineProperties ln = getCTLine(edge, false);
if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill() || !ln.isSetCap()) {
return null;
}
return LineCap.fromOoxmlId(ln.getCap().intValue());
}
public double getBorderRight() {
return getBorderWidth('r');
public void setBorderCap(BorderEdge edge, LineCap cap) {
if (cap == null) {
throw new IllegalArgumentException("LineCap need to be specified.");
}
CTLineProperties ln = setBorderDefaults(edge);
ln.setCap(STLineCap.Enum.forInt(cap.ooxmlId));
}
public void setBorderRightColor(Color color) {
setBorderColor('r', color);
}
public Color getBorderRightColor() {
return getBorderColor('r');
}
public void setBorderTop(double width) {
setBorderWidth('t', width);
}
public double getBorderTop() {
return getBorderWidth('t');
}
public void setBorderTopColor(Color color) {
setBorderColor('t', color);
}
public Color getBorderTopColor() {
return getBorderColor('t');
}
public void setBorderBottom(double width) {
setBorderWidth('b', width);
}
public double getBorderBottom() {
return getBorderWidth('b');
}
public void setBorderBottomColor(Color color) {
setBorderColor('b', color);
}
public Color getBorderBottomColor(){
return getBorderColor('b');
}
/**
* Specifies a solid color fill. The shape is filled entirely with the specified color.

View File

@ -54,8 +54,7 @@ public class XSLFTextBox extends XSLFAutoShape
prst.setPrst(STShapeType.RECT);
prst.addNewAvLst();
CTTextBody txBody = ct.addNewTxBody();
txBody.addNewBodyPr();
txBody.addNewLstStyle();
XSLFAutoShape.initTextBody(txBody);
return ct;
}

View File

@ -32,7 +32,26 @@ import org.apache.poi.util.Units;
import org.apache.poi.xslf.model.ParagraphPropertyFetcher;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.*;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextAutonumberBullet;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBulletSizePercent;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBulletSizePoint;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharBullet;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextField;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextNormalAutofit;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextSpacing;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextTabStop;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextTabStopList;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAutonumberScheme;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextFontAlignType;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
@ -100,6 +119,7 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr
}
@Override
public List<XSLFTextRun> getTextRuns(){
return _runs;
}

View File

@ -206,12 +206,7 @@ public class XSLFTextRun implements TextRun {
}
}
/**
* Specifies the typeface, or name of the font that is to be used for this text run.
*
* @param typeface the font to apply to this text run.
* The value of <code>null</code> unsets the Typeface attrubute from the underlying xml.
*/
@Override
public void setFontFamily(String typeface){
setFontFamily(typeface, (byte)-1, (byte)-1, false);
}
@ -236,9 +231,7 @@ public class XSLFTextRun implements TextRun {
}
}
/**
* @return font family or null if not set
*/
@Override
public String getFontFamily(){
final XSLFTheme theme = _p.getParentShape().getSheet().getTheme();
@ -281,18 +274,12 @@ public class XSLFTextRun implements TextRun {
return visitor.getValue() == null ? 0 : visitor.getValue();
}
/**
* Specifies whether a run of text will be formatted as strikethrough text.
*
* @param strike whether a run of text will be formatted as strikethrough text.
*/
@Override
public void setStrikethrough(boolean strike) {
getRPr().setStrike(strike ? STTextStrikeType.SNG_STRIKE : STTextStrikeType.NO_STRIKE);
}
/**
* @return whether a run of text will be formatted as strikethrough text. Default is false.
*/
@Override
public boolean isStrikethrough() {
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){
public boolean fetch(CTTextCharacterProperties props){
@ -307,9 +294,7 @@ public class XSLFTextRun implements TextRun {
return fetcher.getValue() == null ? false : fetcher.getValue();
}
/**
* @return whether a run of text will be formatted as a superscript text. Default is false.
*/
@Override
public boolean isSuperscript() {
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){
public boolean fetch(CTTextCharacterProperties props){
@ -357,9 +342,7 @@ public class XSLFTextRun implements TextRun {
setBaselineOffset(flag ? -25.0 : 0.);
}
/**
* @return whether a run of text will be formatted as a superscript text. Default is false.
*/
@Override
public boolean isSubscript() {
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){
public boolean fetch(CTTextCharacterProperties props){
@ -392,18 +375,12 @@ public class XSLFTextRun implements TextRun {
return fetcher.getValue() == null ? TextCap.NONE : fetcher.getValue();
}
/**
* Specifies whether this run of text will be formatted as bold text
*
* @param bold whether this run of text will be formatted as bold text
*/
@Override
public void setBold(boolean bold){
getRPr().setB(bold);
}
/**
* @return whether this run of text is formatted as bold text
*/
@Override
public boolean isBold(){
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){
public boolean fetch(CTTextCharacterProperties props){
@ -418,16 +395,12 @@ public class XSLFTextRun implements TextRun {
return fetcher.getValue() == null ? false : fetcher.getValue();
}
/**
* @param italic whether this run of text is formatted as italic text
*/
@Override
public void setItalic(boolean italic){
getRPr().setI(italic);
}
/**
* @return whether this run of text is formatted as italic text
*/
@Override
public boolean isItalic(){
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){
public boolean fetch(CTTextCharacterProperties props){
@ -442,16 +415,12 @@ public class XSLFTextRun implements TextRun {
return fetcher.getValue() == null ? false : fetcher.getValue();
}
/**
* @param underline whether this run of text is formatted as underlined text
*/
public void setUnderline(boolean underline) {
@Override
public void setUnderlined(boolean underline) {
getRPr().setU(underline ? STTextUnderlineType.SNG : STTextUnderlineType.NONE);
}
/**
* @return whether this run of text is formatted as underlined text
*/
@Override
public boolean isUnderlined(){
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){
public boolean fetch(CTTextCharacterProperties props){
@ -501,6 +470,7 @@ public class XSLFTextRun implements TextRun {
CTPlaceholder ph = shape.getCTPlaceholder();
if (ph == null){
// if it is a plain text box then take defaults from presentation.xml
@SuppressWarnings("resource")
XMLSlideShow ppt = sheet.getSlideShow();
CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(_p.getIndentLevel());
if (themeProps != null) {
@ -543,7 +513,7 @@ public class XSLFTextRun implements TextRun {
if(italic != isItalic()) setItalic(italic);
boolean underline = r.isUnderlined();
if(underline != isUnderlined()) setUnderline(underline);
if(underline != isUnderlined()) setUnderlined(underline);
boolean strike = r.isStrikethrough();
if(strike != isStrikethrough()) setStrikethrough(strike);

View File

@ -37,8 +37,10 @@ import org.apache.poi.xslf.model.TextBodyPropertyFetcher;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextListStyle;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextWrappingType;
@ -91,10 +93,52 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
txBody.setPArray(null); // remove any existing paragraphs
}
public void setText(String text){
clearText();
@Override
public XSLFTextRun setText(String text) {
// copy properties from first paragraph / textrun
CTTextParagraphProperties pPr = null;
CTTextCharacterProperties rPr = null;
if (!_paragraphs.isEmpty()) {
XSLFTextParagraph p0 = _paragraphs.get(0);
pPr = p0.getXmlObject().getPPr();
if (!p0.getTextRuns().isEmpty()) {
XSLFTextRun r0 = p0.getTextRuns().get(0);
rPr = r0.getXmlObject().getRPr();
}
}
addNewTextParagraph().addNewTextRun().setText(text);
// can't call clearText otherwise we receive a XmlValueDisconnectedException
_paragraphs.clear();
CTTextBody txBody = getTextBody(true);
int cntPs = txBody.sizeOfPArray();
// split text by paragraph and new line char
XSLFTextRun r = null;
for (String paraText : text.split("\\r\\n?|\\n")) {
XSLFTextParagraph para = addNewTextParagraph();
if (pPr != null) {
para.getXmlObject().setPPr(pPr);
}
boolean first = true;
for (String runText : paraText.split("[\u000b]")) {
if (!first) {
para.addLineBreak();
}
r = para.addNewTextRun();
r.setText(runText);
if (rPr != null) {
r.getXmlObject().setRPr(rPr);
}
first = false;
}
}
// simply setting a new pArray leads to XmlValueDisconnectedException
for (int i = cntPs-1; i >= 0; i--) {
txBody.removeP(i);
}
return r;
}
@Override
@ -115,13 +159,7 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
return paragraph;
}
/**
* Sets the type of vertical alignment for the text.
*
* @param anchor - the type of alignment.
* A {@code null} values unsets this property.
*/
@Override
public void setVerticalAlignment(VerticalAlignment anchor){
CTTextBodyProperties bodyPr = getTextBodyPr();
if (bodyPr != null) {
@ -133,11 +171,7 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
}
}
/**
* Returns the type of vertical alignment for the text.
*
* @return the type of vertical alignment
*/
@Override
public VerticalAlignment getVerticalAlignment(){
PropertyFetcher<VerticalAlignment> fetcher = new TextBodyPropertyFetcher<VerticalAlignment>(){
public boolean fetch(CTTextBodyProperties props){
@ -153,14 +187,7 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
return fetcher.getValue() == null ? VerticalAlignment.TOP : fetcher.getValue();
}
/**
* 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()
*/
@Override
public void setHorizontalCentered(Boolean isCentered){
CTTextBodyProperties bodyPr = getTextBodyPr();
if (bodyPr != null) {
@ -369,10 +396,15 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
return insets;
}
@Override
public void setInsets(Insets2D insets) {
setTopInset(insets.top);
setLeftInset(insets.left);
setBottomInset(insets.bottom);
setRightInset(insets.right);
}
/**
* @return whether to wrap words within the bounding rectangle
*/
@Override
public boolean getWordWrap(){
PropertyFetcher<Boolean> fetcher = new TextBodyPropertyFetcher<Boolean>(){
public boolean fetch(CTTextBodyProperties props){
@ -387,10 +419,7 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
return fetcher.getValue() == null ? true : fetcher.getValue();
}
/**
*
* @param wrap whether to wrap words within the bounding rectangle
*/
@Override
public void setWordWrap(boolean wrap){
CTTextBodyProperties bodyPr = getTextBodyPr();
if (bodyPr != null) {
@ -532,4 +561,45 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
tgtP.copy(srcP);
}
}
@Override
public void setTextPlaceholder(TextPlaceholder placeholder) {
switch (placeholder) {
default:
case NOTES:
case HALF_BODY:
case QUARTER_BODY:
case BODY:
setPlaceholder(Placeholder.BODY);
break;
case TITLE:
setPlaceholder(Placeholder.TITLE);
break;
case CENTER_BODY:
setPlaceholder(Placeholder.BODY);
setHorizontalCentered(true);
break;
case CENTER_TITLE:
setPlaceholder(Placeholder.CENTERED_TITLE);
break;
case OTHER:
setPlaceholder(Placeholder.CONTENT);
break;
}
}
@Override
public TextPlaceholder getTextPlaceholder() {
Placeholder ph = getTextType();
if (ph == null) return TextPlaceholder.BODY;
switch (ph) {
case BODY: return TextPlaceholder.BODY;
case TITLE: return TextPlaceholder.TITLE;
case CENTERED_TITLE: return TextPlaceholder.CENTER_TITLE;
default:
case CONTENT: return TextPlaceholder.OTHER;
}
}
}

View File

@ -268,7 +268,7 @@ public class TestXSLFAutoShape {
assertFalse(r.isUnderlined());
assertFalse(r.getXmlObject().getRPr().isSetU());
r.setUnderline(true);
r.setUnderlined(true);
assertTrue(r.isUnderlined());
assertEquals(STTextUnderlineType.SNG, r.getXmlObject().getRPr().getU());

View File

@ -20,13 +20,16 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.io.IOException;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.xslf.XSLFTestDataSamples;
import org.junit.Test;
public class TestXSLFNotes {
@Test
public void createNewNote() {
public void createNewNote() throws IOException {
XMLSlideShow ppt = new XMLSlideShow();
XSLFSlide slide1 = ppt.createSlide();
@ -48,10 +51,12 @@ public class TestXSLFNotes {
}
assertNotNull(note);
assertEquals("New Note", note);
ppt.close();
}
@Test
public void addNote() {
public void addNote() throws IOException {
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("sample.pptx");
@ -69,10 +74,12 @@ public class TestXSLFNotes {
}
assertNotNull(note);
assertEquals("New Note", note);
ppt.close();
}
@Test
public void replaceNotes() {
public void replaceNotes() throws IOException {
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("sample.pptx");
@ -93,5 +100,7 @@ public class TestXSLFNotes {
assertNotNull(note);
assertEquals("New Note", note);
}
ppt.close();
}
}

View File

@ -28,6 +28,7 @@ import java.io.IOException;
import java.util.List;
import org.apache.poi.sl.draw.geom.TestPresetGeometries;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
import org.apache.poi.util.Units;
@ -168,7 +169,7 @@ public class TestXSLFSimpleShape {
}
@Test
public void testDefaultProperties() {
public void testDefaultProperties() throws IOException {
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");
XSLFSlide slide6 = ppt.getSlides().get(5);
@ -234,10 +235,12 @@ public class TestXSLFSimpleShape {
assertEquals(50000, ref5.getLumModArray(0).getVal());
assertEquals("accent1", ref5.getVal().toString());
assertEquals(new Color(79, 129, 189), s5.getFillColor());
ppt.close();
}
@Test
public void testAnchor(){
public void testAnchor() throws IOException {
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");
List<XSLFSlide> slide = ppt.getSlides();
@ -267,6 +270,7 @@ public class TestXSLFSimpleShape {
assertNotNull(layout5.getSlideMaster().getTextShapeByType(Placeholder.TITLE).getSpPr().getXfrm());
assertEquals(shTitle.getAnchor(), layout5.getSlideMaster().getTextShapeByType(Placeholder.TITLE).getAnchor());
ppt.close();
}
@SuppressWarnings({ "deprecation", "unused" })

View File

@ -16,23 +16,29 @@
==================================================================== */
package org.apache.poi.xslf.usermodel;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.awt.Color;
import java.io.IOException;
import java.util.List;
import org.apache.poi.sl.usermodel.TableCell.BorderEdge;
import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.xslf.XSLFTestDataSamples;
import org.junit.Test;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;
import java.awt.Color;
import java.util.List;
/**
* @author Yegor Kozlov
*/
public class TestXSLFTable {
@Test
public void testRead(){
public void testRead() throws IOException {
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");
XSLFSlide slide = ppt.getSlides().get(3);
@ -69,10 +75,12 @@ public class TestXSLFTable {
assertEquals("A1", cells1.get(0).getText());
assertEquals("B1", cells1.get(1).getText());
assertEquals("C1", cells1.get(2).getText());
ppt.close();
}
@Test
public void testCreate() {
public void testCreate() throws IOException {
XMLSlideShow ppt = new XMLSlideShow();
XSLFSlide slide = ppt.createSlide();
@ -121,38 +129,21 @@ public class TestXSLFTable {
cell1.addNewTextParagraph().addNewTextRun().setText("Apache");
assertEquals("Apache", cell1.getText());
assertEquals(1.0, cell1.getBorderBottom(), 0);
cell1.setBorderBottom(2.0);
assertEquals(2.0, cell1.getBorderBottom(), 0);
assertNull(cell1.getBorderBottomColor());
cell1.setBorderBottomColor(Color.yellow);
assertEquals(Color.yellow, cell1.getBorderBottomColor());
assertEquals(1.0, cell1.getBorderTop(), 0);
cell1.setBorderTop(2.0);
assertEquals(2.0, cell1.getBorderTop(), 0);
assertNull(cell1.getBorderTopColor());
cell1.setBorderTopColor(Color.yellow);
assertEquals(Color.yellow, cell1.getBorderTopColor());
assertEquals(1.0, cell1.getBorderLeft(), 0);
cell1.setBorderLeft(2.0);
assertEquals(2.0, cell1.getBorderLeft(), 0);
assertNull(cell1.getBorderLeftColor());
cell1.setBorderLeftColor(Color.yellow);
assertEquals(Color.yellow, cell1.getBorderLeftColor());
assertEquals(1.0, cell1.getBorderRight(), 0);
cell1.setBorderRight(2.0);
assertEquals(2.0, cell1.getBorderRight(), 0);
assertNull(cell1.getBorderRightColor());
cell1.setBorderRightColor(Color.yellow);
assertEquals(Color.yellow, cell1.getBorderRightColor());
for (BorderEdge edge : BorderEdge.values()) {
assertNull(cell1.getBorderWidth(edge));
cell1.setBorderWidth(edge, 2.0);
assertEquals(2.0, cell1.getBorderWidth(edge), 0);
assertNull(cell1.getBorderColor(edge));
cell1.setBorderColor(edge, Color.yellow);
assertEquals(Color.yellow, cell1.getBorderColor(edge));
}
assertEquals(VerticalAlignment.TOP, cell1.getVerticalAlignment());
cell1.setVerticalAlignment(VerticalAlignment.MIDDLE);
assertEquals(VerticalAlignment.MIDDLE, cell1.getVerticalAlignment());
cell1.setVerticalAlignment(null);
assertEquals(VerticalAlignment.TOP, cell1.getVerticalAlignment());
ppt.close();
}
}

View File

@ -19,6 +19,9 @@ package org.apache.poi.xslf.usermodel;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.io.IOException;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.junit.Test;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
@ -28,7 +31,7 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties
public class TestXSLFTextBox {
@Test
public void testPlaceholder() {
public void testPlaceholder() throws IOException {
XMLSlideShow ppt = new XMLSlideShow();
XSLFSlide slide = ppt.createSlide();
@ -39,13 +42,15 @@ public class TestXSLFTextBox {
shape.setPlaceholder(null);
assertNull(shape.getTextType());
shape.setText("Apache POI");
ppt.close();
}
/**
* text box inherits default text proeprties from presentation.xml
*/
@Test
public void testDefaultTextStyle() {
public void testDefaultTextStyle() throws IOException {
XMLSlideShow ppt = new XMLSlideShow();
XSLFSlide slide = ppt.createSlide();
@ -79,5 +84,7 @@ public class TestXSLFTextBox {
pPr.unsetSz(); // Should never be
assertNull(r.getFontSize());
ppt.close();
}
}

View File

@ -28,6 +28,7 @@ import java.awt.Color;
import java.io.IOException;
import java.util.List;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.xslf.XSLFTestDataSamples;
@ -45,7 +46,7 @@ import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
public class TestXSLFTextShape {
@Test
public void testLayouts(){
public void testLayouts() throws IOException {
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("layouts.pptx");
List<XSLFSlide> slide = ppt.getSlides();
@ -57,6 +58,8 @@ public class TestXSLFTextShape {
verifySlide7(slide.get(6));
verifySlide8(slide.get(7));
verifySlide10(slide.get(9));
ppt.close();
}
void verifySlide1(XSLFSlide slide){

View File

@ -297,7 +297,7 @@ public final class PPGraphics2D extends Graphics2D implements Cloneable {
txt.setTopInset(0);
txt.setLeftInset(0);
txt.setRightInset(0);
txt.setWordWrap(HSLFTextBox.WrapNone);
txt.setWordWrap(false);
txt.setHorizontalCentered(false);
txt.setVerticalAlignment(VerticalAlignment.MIDDLE);
@ -1826,7 +1826,7 @@ public final class PPGraphics2D extends Graphics2D implements Cloneable {
float[] dash = bs.getDashArray();
if (dash != null) {
//TODO: implement more dashing styles
shape.setLineDashing(StrokeStyle.LineDash.DASH);
shape.setLineDash(StrokeStyle.LineDash.DASH);
}
}
}

View File

@ -1,96 +0,0 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hslf.model;
import org.apache.poi.ddf.*;
import org.apache.poi.hslf.record.OEPlaceholderAtom;
import org.apache.poi.hslf.usermodel.HSLFShape;
import org.apache.poi.hslf.usermodel.HSLFTextBox;
import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.sl.usermodel.ShapeContainer;
import java.io.ByteArrayOutputStream;
/**
* Represents a Placeholder in PowerPoint.
*
* @author Yegor Kozlov
*/
public final class Placeholder extends HSLFTextBox {
protected Placeholder(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
super(escherRecord, parent);
}
public Placeholder(ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
super(parent);
}
public Placeholder(){
super();
}
/**
* Create a new Placeholder and initialize internal structures
*
* @return the created <code>EscherContainerRecord</code> which holds shape data
*/
protected EscherContainerRecord createSpContainer(boolean isChild){
_escherContainer = super.createSpContainer(isChild);
EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
spRecord.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HAVEMASTER);
EscherClientDataRecord cldata = new EscherClientDataRecord();
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);
oep.setPlaceholderId(OEPlaceholderAtom.Body);
//convert hslf into ddf record
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
oep.writeOut(out);
} catch(Exception e){
throw new HSLFException(e);
}
cldata.setRemainingData(out.toByteArray());
//append placeholder container before EscherTextboxRecord
_escherContainer.addChildBefore(cldata, EscherTextboxRecord.RECORD_ID);
return _escherContainer;
}
}

View File

@ -67,7 +67,7 @@ public class HSLFAutoShape extends HSLFTextShape implements AutoShape<HSLFShape,
protected void setDefaultTextProperties(HSLFTextParagraph _txtrun){
setVerticalAlignment(VerticalAlignment.MIDDLE);
setHorizontalCentered(true);
setWordWrap(HSLFTextBox.WrapNone);
setWordWrap(false);
}
/**

View File

@ -43,7 +43,6 @@ import org.apache.poi.util.Units;
*/
public class HSLFGroupShape extends HSLFShape
implements HSLFShapeContainer, GroupShape<HSLFShape,HSLFTextParagraph> {
/**
* Create a new ShapeGroup. This constructor is used when a new shape is created.
*
@ -73,34 +72,16 @@ implements HSLFShapeContainer, GroupShape<HSLFShape,HSLFTextParagraph> {
super(escherRecord, parent);
}
/**
* Sets the anchor (the bounding box rectangle) of this shape.
* All coordinates should be expressed in Master units (576 dpi).
*
* @param anchor new anchor
*/
public void setAnchor(java.awt.Rectangle anchor){
@Override
public void setAnchor(Rectangle anchor) {
EscherClientAnchorRecord clientAnchor = getEscherChild(EscherClientAnchorRecord.RECORD_ID);
//hack. internal variable EscherClientAnchorRecord.shortRecord can be
//initialized only in fillFields(). We need to set shortRecord=false;
byte[] header = new byte[16];
LittleEndian.putUShort(header, 0, 0);
LittleEndian.putUShort(header, 2, 0);
LittleEndian.putInt(header, 4, 8);
clientAnchor.fillFields(header, 0, null);
boolean isInitialized = !(clientAnchor.getDx1() == 0 && clientAnchor.getRow1() == 0);
clientAnchor.setFlag((short)Units.pointsToMaster(anchor.y));
clientAnchor.setCol1((short)Units.pointsToMaster(anchor.x));
clientAnchor.setDx1((short)Units.pointsToMaster(anchor.width + anchor.x));
clientAnchor.setRow1((short)Units.pointsToMaster(anchor.height + anchor.y));
EscherSpgrRecord spgr = getEscherChild(EscherSpgrRecord.RECORD_ID);
spgr.setRectX1(Units.pointsToMaster(anchor.x));
spgr.setRectY1(Units.pointsToMaster(anchor.y));
spgr.setRectX2(Units.pointsToMaster(anchor.x + anchor.width));
spgr.setRectY2(Units.pointsToMaster(anchor.y + anchor.height));
if (isInitialized) {
moveAndScale(anchor);
} else {
setExteriorAnchor(anchor);
}
}
@Override
@ -116,7 +97,6 @@ implements HSLFShapeContainer, GroupShape<HSLFShape,HSLFTextParagraph> {
spgr.setRectY1(y1);
spgr.setRectX2(x2);
spgr.setRectY2(y2);
}
@Override
@ -129,6 +109,27 @@ implements HSLFShapeContainer, GroupShape<HSLFShape,HSLFTextParagraph> {
return new Rectangle(x1,y1,x2-x1,y2-y1);
}
protected void setExteriorAnchor(Rectangle anchor) {
EscherClientAnchorRecord clientAnchor = getEscherChild(EscherClientAnchorRecord.RECORD_ID);
//hack. internal variable EscherClientAnchorRecord.shortRecord can be
//initialized only in fillFields(). We need to set shortRecord=false;
byte[] header = new byte[16];
LittleEndian.putUShort(header, 0, 0);
LittleEndian.putUShort(header, 2, 0);
LittleEndian.putInt(header, 4, 8);
clientAnchor.fillFields(header, 0, null);
// All coordinates need to be converted to Master units (576 dpi)
clientAnchor.setFlag((short)Units.pointsToMaster(anchor.y));
clientAnchor.setCol1((short)Units.pointsToMaster(anchor.x));
clientAnchor.setDx1((short)Units.pointsToMaster(anchor.width + anchor.x));
clientAnchor.setRow1((short)Units.pointsToMaster(anchor.height + anchor.y));
// TODO: does this make sense?
setInteriorAnchor(anchor);
}
/**
* Create a new ShapeGroup and create an instance of <code>EscherSpgrContainer</code> which represents a group of shapes
*/
@ -174,23 +175,22 @@ implements HSLFShapeContainer, GroupShape<HSLFShape,HSLFTextParagraph> {
}
/**
* Moves this <code>ShapeGroup</code> to the specified location.
* <p>
* @param x the x coordinate of the top left corner of the shape in new location
* @param y the y coordinate of the top left corner of the shape in new location
* Moves and scales this <code>ShapeGroup</code> to the specified anchor.
*/
public void moveTo(int x, int y){
Rectangle anchor = getAnchor();
int dx = x - anchor.x;
int dy = y - anchor.y;
anchor.translate(dx, dy);
setAnchor(anchor);
protected void moveAndScale(Rectangle anchorDest){
Rectangle anchorSrc = getAnchor();
double scaleX = (anchorSrc.width == 0) ? 0 : anchorDest.width / (double)anchorSrc.width;
double scaleY = (anchorSrc.height == 0) ? 0 : anchorDest.height / (double)anchorSrc.height;
setExteriorAnchor(anchorDest);
for (HSLFShape shape : getShapes()) {
Rectangle chanchor = shape.getAnchor();
chanchor.translate(dx, dy);
shape.setAnchor(chanchor);
int x = (int)Math.rint(anchorDest.x+(chanchor.x-anchorSrc.x)*scaleX);
int y = (int)Math.rint(anchorDest.y+(chanchor.y-anchorSrc.y)*scaleY);
int width = (int)Math.rint(chanchor.width*scaleX);
int height = (int)Math.rint(chanchor.height*scaleY);
shape.setAnchor(new Rectangle(x, y, width, height));
}
}
@ -262,9 +262,6 @@ implements HSLFShapeContainer, GroupShape<HSLFShape,HSLFTextParagraph> {
throw new UnsupportedOperationException();
}
/**
* @return the shapes contained in this group container
*/
@Override
public List<HSLFShape> getShapes() {
// Out escher container record should contain several

View File

@ -0,0 +1,55 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hslf.usermodel;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.sl.usermodel.ShapeContainer;
/**
* Represents a Placeholder in PowerPoint.
*
* @author Yegor Kozlov
*/
public final class HSLFPlaceholder extends HSLFTextBox {
protected HSLFPlaceholder(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
super(escherRecord, parent);
}
public HSLFPlaceholder(ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
super(parent);
}
public HSLFPlaceholder(){
super();
}
/**
* Create a new Placeholder and initialize internal structures
*
* @return the created <code>EscherContainerRecord</code> which holds shape data
*/
protected EscherContainerRecord createSpContainer(boolean isChild){
_escherContainer = super.createSpContainer(isChild);
setPlaceholder(Placeholder.BODY);
return _escherContainer;
}
}

View File

@ -116,19 +116,11 @@ public abstract class HSLFShape implements Shape<HSLFShape,HSLFTextParagraph> {
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 implements Shape<HSLFShape,HSLFTextParagraph> {
* @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);

View File

@ -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");
case NOT_PRIMITIVE:
shape = createNonPrimitive(spContainer, parent);
break;
default:
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;
}
default:
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;
}
}

View File

@ -458,7 +458,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
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;
}

View File

@ -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;
@ -146,12 +147,33 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
return clr == null ? Color.black : clr;
}
/**
* 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 extends HSLFShape implements SimpleShape<H
*
* @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);
}
@ -204,7 +226,7 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
}
public LineDash getLineDash() {
return HSLFSimpleShape.this.getLineDashing();
return HSLFSimpleShape.this.getLineDash();
}
public LineCompound getLineCompound() {
@ -218,19 +240,13 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
};
}
/**
* 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);
}
@ -475,4 +491,123 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
}
};
}
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);
}
}
}
}

View File

@ -27,7 +27,6 @@ import org.apache.poi.ddf.EscherDggRecord;
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 HSLFSheet implements Slide<HSLFShape,HSLFTe
* @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");

View File

@ -531,9 +531,7 @@ public final class HSLFSlideShow implements SlideShow<HSLFShape,HSLFTextParagrap
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 implements SlideShow<HSLFShape,HSLFTextParagrap
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));

View File

@ -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,7 +59,7 @@ implements HSLFShapeContainer, TableShape<HSLFShape,HSLFTextParagraph> {
* @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);
}
@ -76,7 +70,7 @@ implements HSLFShapeContainer, TableShape<HSLFShape,HSLFTextParagraph> {
* @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, TableShape<HSLFShape,HSLFTextParagraph> {
}
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, TableShape<HSLFShape,HSLFTextParagraph> {
}
/**
* 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, TableShape<HSLFShape,HSLFTextParagraph> {
return cells[row][col];
}
@Override
public int getNumberOfColumns() {
return cells[0].length;
}
@Override
public int getNumberOfRows() {
return cells.length;
}
@ -141,88 +138,169 @@ implements HSLFShapeContainer, TableShape<HSLFShape,HSLFTextParagraph> {
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);
HSLFLine bt = c.getBorderTop();
if(bt != null) addShape(bt);
HSLFLine br = c.getBorderRight();
if(br != null) addShape(br);
HSLFLine bb = c.getBorderBottom();
if(bb != null) addShape(bb);
HSLFLine bl = c.getBorderLeft();
if(bl != null) addShape(bl);
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);
}
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;
}
}
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");
}
Collections.sort(htc, new TableCellComparator());
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()][]);
}
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));
}
}
private void fitLinesToCells() {
List<LineRect> lines = new ArrayList<LineRect>();
for (HSLFShape h : getShapes()) {
if (h instanceof HSLFLine) {
lines.add(new LineRect((HSLFLine)h));
}
}
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(){
List<HSLFShape> shapeList = getShapes();
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());
}
}
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());
}
}
cellListToArray();
fitLinesToCells();
}
/**
@ -232,151 +310,102 @@ implements HSLFShapeContainer, TableShape<HSLFShape,HSLFTextParagraph> {
*/
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);
@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 < 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);
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));
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++;
}
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;
}
/**
* 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);
}
}
}
@Override
protected void moveAndScale(Rectangle anchorDest){
super.moveAndScale(anchorDest);
updateRowHeightsProperty();
}
/**
* 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);
}
}
}
}
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;
}
/**
* 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);
}
}
}

View File

@ -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 HSLFTextBox implements TableCell<HSLFSh
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 HSLFTextBox implements TableCell<HSLFSh
* @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 HSLFTextBox implements TableCell<HSLFSh
* @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 HSLFTextBox implements TableCell<HSLFSh
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 setBorderLeft(HSLFLine line) {
if(line != null) anchorBorder(HSLFTable.BORDER_LEFT, line);
this.borderLeft = line;
}
public HSLFLine getBorderRight() {
return borderRight;
}
public void setBorderRight(HSLFLine line) {
if(line != null) anchorBorder(HSLFTable.BORDER_RIGHT, line);
this.borderRight = line;
}
public HSLFLine getBorderTop() {
return borderTop;
}
public void setBorderTop(HSLFLine line) {
if(line != null) anchorBorder(HSLFTable.BORDER_TOP, line);
this.borderTop = line;
}
public HSLFLine getBorderBottom() {
return borderBottom;
}
public void setBorderBottom(HSLFLine line) {
if(line != null) anchorBorder(HSLFTable.BORDER_BOTTOM, line);
this.borderBottom = line;
}
public void setAnchor(Rectangle anchor){
super.setAnchor(anchor);
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);
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 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();
}
@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 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);
}
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();
}
}
@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();
}
}
protected HSLFTableCell getSiblingCell(int row, int col) {
return getParent().getRelativeCell(this, row, col);
}
/**
* 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;
}
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());
}
@Override
public HSLFTable getParent() {
return (HSLFTable)super.getParent();
}
}

View File

@ -109,7 +109,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
* @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 implements TextParagraph<HSLFShape,HSLFText
_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;
}
@ -278,7 +275,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
}
/** Numbered List info */
public void setStyleTextProp9Atom(final StyleTextProp9Atom styleTextProp9Atom) {
public void setStyleTextProp9Atom(final StyleTextProp9Atom styleTextProp9Atom) {
this.styleTextProp9Atom = styleTextProp9Atom;
}
@ -889,9 +886,13 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
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 implements TextParagraph<HSLFShape,HSLFText
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);

View File

@ -157,44 +157,32 @@ public final class HSLFTextRun implements TextRun {
// --------------- 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 implements TextRun {
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 implements TextRun {
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 implements TextRun {
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 implements TextRun {
return TextCap.NONE;
}
@Override
public boolean isSubscript() {
return false;
return getSuperscript() < 0;
}
@Override
public boolean isSuperscript() {
return false;
return getSuperscript() > 0;
}
public byte getPitchAndFamily() {

View File

@ -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 java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.ddf.*;
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,HSLFTextParagraph> {
/* 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,HSLFTextParagraph> {
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
@ -354,20 +374,32 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
}
}
public void setVerticalAlignment(VerticalAlignment vAlign) {
setAlignment(isHorizontalCentered(), vAlign);
@Override
public void setHorizontalCentered(Boolean isCentered) {
setAlignment(isCentered, getVerticalAlignment());
}
/**
* 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 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;
}
}
@Override
public void setVerticalAlignment(VerticalAlignment vAlign) {
setAlignment(isHorizontalCentered(), vAlign);
}
/**
@ -479,12 +511,6 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
setEscherProperty(propId, Units.toEMU(margin));
}
@Override
public boolean getWordWrap(){
int ww = getWordWrapEx();
return (ww != WrapNone);
}
/**
* Returns the value indicating word wrap.
*
@ -505,10 +531,21 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
* @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.
*/
@ -699,6 +736,14 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
return insets;
}
@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);
@ -747,14 +792,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
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,HSLFTextParagraph> {
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;
}
}
}

View File

@ -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);

View File

@ -91,7 +91,7 @@ public final class TestShapes {
java.awt.Rectangle lineAnchor = new java.awt.Rectangle(100, 200, 50, 60);
line.setAnchor(lineAnchor);
line.setLineWidth(3);
line.setLineDashing(LineDash.DASH);
line.setLineDash(LineDash.DASH);
line.setLineColor(Color.red);
slide.addShape(line);
@ -99,7 +99,7 @@ public final class TestShapes {
java.awt.Rectangle ellipseAnchor = new Rectangle(320, 154, 55, 111);
ellipse.setAnchor(ellipseAnchor);
ellipse.setLineWidth(2);
ellipse.setLineDashing(LineDash.SOLID);
ellipse.setLineDash(LineDash.SOLID);
ellipse.setLineColor(Color.green);
ellipse.setFillColor(Color.lightGray);
slide.addShape(ellipse);

View File

@ -57,15 +57,15 @@ public final class TestTable {
HSLFSlide slide = ppt.createSlide();
HSLFTable tbl = new HSLFTable(2, 5);
slide.addShape(tbl);
HSLFTable tbl = slide.createTable(2, 5);
HSLFTableCell cell = tbl.getCell(0, 0);
//table cells have type=TextHeaderAtom.OTHER_TYPE, see bug #46033
assertEquals(TextHeaderAtom.OTHER_TYPE, cell.getTextParagraphs().get(0).getRunType());
assertTrue(slide.getShapes().get(0) instanceof HSLFTable);
HSLFTable tbl2 = (HSLFTable)slide.getShapes().get(0);
HSLFShape tblSh = slide.getShapes().get(0);
assertTrue(tblSh instanceof HSLFTable);
HSLFTable tbl2 = (HSLFTable)tblSh;
assertEquals(tbl.getNumberOfColumns(), tbl2.getNumberOfColumns());
assertEquals(tbl.getNumberOfRows(), tbl2.getNumberOfRows());
@ -89,10 +89,9 @@ public final class TestTable {
HSLFSlideShow ppt = new HSLFSlideShow();
HSLFSlide slide = ppt.createSlide();
List<HSLFShape> shapes;
HSLFTable tbl1 = new HSLFTable(1, 5);
HSLFTable tbl1 = slide.createTable(1, 5);
assertEquals(5, tbl1.getNumberOfColumns());
assertEquals(1, tbl1.getNumberOfRows());
slide.addShape(tbl1);
shapes = slide.getShapes();
assertEquals(1, shapes.size());
@ -106,14 +105,16 @@ public final class TestTable {
@Test
public void testIllegalCOnstruction(){
HSLFSlideShow ppt = new HSLFSlideShow();
HSLFSlide slide = ppt.createSlide();
try {
new HSLFTable(0, 5);
slide.createTable(0, 5);
fail("Table(rownum, colnum) must throw IllegalArgumentException if any of tghe arguments is less than 1");
} catch (IllegalArgumentException e){
}
try {
new HSLFTable(5, 0);
slide.createTable(5, 0);
fail("Table(rownum, colnum) must throw IllegalArgumentException if any of tghe arguments is less than 1");
} catch (IllegalArgumentException e){

View File

@ -19,22 +19,49 @@
package org.apache.poi.hslf.usermodel;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.awt.Color;
import java.awt.Rectangle;
import java.util.List;
import org.apache.poi.POIDataSamples;
import org.apache.poi.sl.draw.DrawTableShape;
import org.apache.poi.sl.usermodel.StrokeStyle;
import org.junit.Test;
/**
* Test that checks numbered list functionality.
*
* @author Alex Nikiforov [mailto:anikif@gmail.com]
* Table related tests
*/
public class TestTable {
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
@Test
public void moveTable() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow();
HSLFSlide slide = ppt.createSlide();
int rows = 3, cols = 5;
HSLFTable table = slide.createTable(rows, cols);
for (int row=0; row<rows; row++) {
for (int col=0; col<cols; col++) {
HSLFTableCell c = table.getCell(row, col);
c.setText("r"+row+"c"+col);
}
}
new DrawTableShape(table).setAllBorders(1.0, Color.black, StrokeStyle.LineDash.DASH_DOT);
table.setAnchor(new Rectangle(100, 100, 400, 400));
Rectangle rectExp = new Rectangle(420,367,80,133);
Rectangle rectAct = table.getCell(rows-1, cols-1).getAnchor();
assertEquals(rectExp, rectAct);
}
@Test
public void testTable() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("54111.ppt"));

View File

@ -571,4 +571,13 @@ public final class TestTextRun {
}
}
@Test
public void testAppendEmpty() throws IOException {
HSLFSlideShow ppt = new HSLFSlideShow();
HSLFSlide s = ppt.createSlide();
HSLFTextBox title = s.addTitle();
title.setText("");
title.appendText("\n", true);
title.appendText("para", true);
}
}