diff options
author | Andreas Beeker <kiwiwings@apache.org> | 2015-10-29 01:05:27 +0000 |
---|---|---|
committer | Andreas Beeker <kiwiwings@apache.org> | 2015-10-29 01:05:27 +0000 |
commit | eb1e1a28e8fe4815851b283789a2552bbac9afcb (patch) | |
tree | 40273b56cb9179d7341c57f19eac18a13995e02a /src | |
parent | 8f0093e4648f0e9598d26847984eee060535f951 (diff) | |
download | poi-eb1e1a28e8fe4815851b283789a2552bbac9afcb.tar.gz poi-eb1e1a28e8fe4815851b283789a2552bbac9afcb.zip |
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
Diffstat (limited to 'src')
57 files changed, 4028 insertions, 1129 deletions
diff --git a/src/examples/src/org/apache/poi/hslf/examples/ApacheconEU08.java b/src/examples/src/org/apache/poi/hslf/examples/ApacheconEU08.java index c911424726..8101c71f63 100644 --- a/src/examples/src/org/apache/poi/hslf/examples/ApacheconEU08.java +++ b/src/examples/src/org/apache/poi/hslf/examples/ApacheconEU08.java @@ -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); - - HSLFLine border2 = table1.createBorder(); - border2.setLineColor(Color.black); - border2.setLineWidth(2.0); - table1.setOutsideBorders(border2); + DrawTableShape dts = new DrawTableShape(table1); + dts.setAllBorders(1.0, Color.black); + dts.setOutsideBorders(4.0); - table1.setColumnWidth(0, 510); - table1.setRowHeight(0, 60); - table1.setRowHeight(1, 100); - slide.addShape(table1); + table1.setColumnWidth(0, 450); + table1.setRowHeight(0, 50); + table1.setRowHeight(1, 80); - table1.moveTo(100, 100); + Dimension dim = ppt.getPageSize(); + Rectangle oldAnchor = table1.getAnchor(); + table1.setAnchor(new Rectangle((dim.width-450)/2, 100, oldAnchor.width, oldAnchor.height)); - 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); } } diff --git a/src/examples/src/org/apache/poi/hslf/examples/TableDemo.java b/src/examples/src/org/apache/poi/hslf/examples/TableDemo.java index d50855e619..c8a1395902 100644 --- a/src/examples/src/org/apache/poi/hslf/examples/TableDemo.java +++ b/src/examples/src/org/apache/poi/hslf/examples/TableDemo.java @@ -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"); diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial3.java b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial3.java index 54347b4c32..28c1fa3f12 100644 --- a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial3.java +++ b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial3.java @@ -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
*
diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial4.java b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial4.java index ecfc986670..94082a2ef9 100644 --- a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial4.java +++ b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial4.java @@ -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
}
diff --git a/src/java/org/apache/poi/sl/draw/DrawTableShape.java b/src/java/org/apache/poi/sl/draw/DrawTableShape.java index b252ddfda9..ec44d17d6b 100644 --- a/src/java/org/apache/poi/sl/draw/DrawTableShape.java +++ b/src/java/org/apache/poi/sl/draw/DrawTableShape.java @@ -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);
+ }
+ }
+ }
+ }
+ }
+ }
}
diff --git a/src/java/org/apache/poi/sl/draw/SLGraphics.java b/src/java/org/apache/poi/sl/draw/SLGraphics.java new file mode 100644 index 0000000000..2a6d884ca1 --- /dev/null +++ b/src/java/org/apache/poi/sl/draw/SLGraphics.java @@ -0,0 +1,1831 @@ +/* ====================================================================
+ 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.sl.draw;
+
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Paint;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.Toolkit;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.font.TextLayout;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Arc2D;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Line2D;
+import java.awt.geom.RoundRectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+import java.awt.image.ImageObserver;
+import java.awt.image.RenderedImage;
+import java.awt.image.renderable.RenderableImage;
+import java.text.AttributedCharacterIterator;
+import java.util.Map;
+
+import org.apache.poi.sl.usermodel.FreeformShape;
+import org.apache.poi.sl.usermodel.GroupShape;
+import org.apache.poi.sl.usermodel.Insets2D;
+import org.apache.poi.sl.usermodel.SimpleShape;
+import org.apache.poi.sl.usermodel.StrokeStyle;
+import org.apache.poi.sl.usermodel.TextBox;
+import org.apache.poi.sl.usermodel.TextRun;
+import org.apache.poi.sl.usermodel.VerticalAlignment;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+import org.apache.poi.util.SuppressForbidden;
+
+/**
+ * Translates Graphics2D calls into PowerPoint.
+ *
+ * @author Yegor Kozlov
+ */
+public final class SLGraphics extends Graphics2D implements Cloneable {
+
+ protected POILogger log = POILogFactory.getLogger(this.getClass());
+
+ //The ppt object to write into.
+ private GroupShape<?,?> _group;
+
+ private AffineTransform _transform;
+ private Stroke _stroke;
+ private Paint _paint;
+ private Font _font;
+ private Color _foreground;
+ private Color _background;
+ private RenderingHints _hints;
+
+ /**
+ * Construct Java Graphics object which translates graphic calls in ppt drawing layer.
+ *
+ * @param group The shape group to write the graphics calls into.
+ */
+ public SLGraphics(GroupShape<?,?> group){
+ this._group = group;
+
+ _transform = new AffineTransform();
+ _stroke = new BasicStroke();
+ _paint = Color.black;
+ _font = new Font("Arial", Font.PLAIN, 12);
+ _background = Color.black;
+ _foreground = Color.white;
+ _hints = new RenderingHints(null);
+ }
+
+ /**
+ * @return the shape group being used for drawing
+ */
+ public GroupShape<?,?> getShapeGroup(){
+ return _group;
+ }
+
+ /**
+ * Gets the current font.
+ * @return this graphics context's current font.
+ * @see java.awt.Font
+ * @see java.awt.Graphics#setFont(Font)
+ */
+ public Font getFont(){
+ return _font;
+ }
+
+ /**
+ * Sets this graphics context's font to the specified font.
+ * All subsequent text operations using this graphics context
+ * use this font.
+ * @param font the font.
+ * @see java.awt.Graphics#getFont
+ * @see java.awt.Graphics#drawString(java.lang.String, int, int)
+ * @see java.awt.Graphics#drawBytes(byte[], int, int, int, int)
+ * @see java.awt.Graphics#drawChars(char[], int, int, int, int)
+ */
+ public void setFont(Font font){
+ this._font = font;
+ }
+
+ /**
+ * Gets this graphics context's current color.
+ * @return this graphics context's current color.
+ * @see java.awt.Color
+ * @see java.awt.Graphics#setColor
+ */
+ public Color getColor(){
+ return _foreground;
+ }
+
+ /**
+ * Sets this graphics context's current color to the specified
+ * color. All subsequent graphics operations using this graphics
+ * context use this specified color.
+ * @param c the new rendering color.
+ * @see java.awt.Color
+ * @see java.awt.Graphics#getColor
+ */
+ public void setColor(Color c) {
+ setPaint(c);
+ }
+
+ /**
+ * Returns the current <code>Stroke</code> in the
+ * <code>Graphics2D</code> context.
+ * @return the current <code>Graphics2D</code> <code>Stroke</code>,
+ * which defines the line style.
+ * @see #setStroke
+ */
+ public Stroke getStroke(){
+ return _stroke;
+ }
+
+ /**
+ * Sets the <code>Stroke</code> for the <code>Graphics2D</code> context.
+ * @param s the <code>Stroke</code> object to be used to stroke a
+ * <code>Shape</code> during the rendering process
+ */
+ public void setStroke(Stroke s){
+ this._stroke = s;
+ }
+
+ /**
+ * Returns the current <code>Paint</code> of the
+ * <code>Graphics2D</code> context.
+ * @return the current <code>Graphics2D</code> <code>Paint</code>,
+ * which defines a color or pattern.
+ * @see #setPaint
+ * @see java.awt.Graphics#setColor
+ */
+ public Paint getPaint(){
+ return _paint;
+ }
+
+ /**
+ * Sets the <code>Paint</code> attribute for the
+ * <code>Graphics2D</code> context. Calling this method
+ * with a <code>null</code> <code>Paint</code> object does
+ * not have any effect on the current <code>Paint</code> attribute
+ * of this <code>Graphics2D</code>.
+ * @param paint the <code>Paint</code> object to be used to generate
+ * color during the rendering process, or <code>null</code>
+ * @see java.awt.Graphics#setColor
+ */
+ public void setPaint(Paint paint){
+ if(paint == null) return;
+
+ this._paint = paint;
+ if (paint instanceof Color) _foreground = (Color)paint;
+ }
+
+ /**
+ * Returns a copy of the current <code>Transform</code> in the
+ * <code>Graphics2D</code> context.
+ * @return the current <code>AffineTransform</code> in the
+ * <code>Graphics2D</code> context.
+ * @see #_transform
+ * @see #setTransform
+ */
+ public AffineTransform getTransform(){
+ return new AffineTransform(_transform);
+ }
+
+ /**
+ * Sets the <code>Transform</code> in the <code>Graphics2D</code>
+ * context.
+ * @param Tx the <code>AffineTransform</code> object to be used in the
+ * rendering process
+ * @see #_transform
+ * @see AffineTransform
+ */
+ public void setTransform(AffineTransform Tx) {
+ _transform = new AffineTransform(Tx);
+ }
+
+ /**
+ * Strokes the outline of a <code>Shape</code> using the settings of the
+ * current <code>Graphics2D</code> context. The rendering attributes
+ * applied include the <code>Clip</code>, <code>Transform</code>,
+ * <code>Paint</code>, <code>Composite</code> and
+ * <code>Stroke</code> attributes.
+ * @param shape the <code>Shape</code> to be rendered
+ * @see #setStroke
+ * @see #setPaint
+ * @see java.awt.Graphics#setColor
+ * @see #_transform
+ * @see #setTransform
+ * @see #clip
+ * @see #setClip
+ * @see #setComposite
+ */
+ public void draw(Shape shape){
+ GeneralPath path = new GeneralPath(_transform.createTransformedShape(shape));
+ FreeformShape<?,?> p = _group.createFreeform();
+ p.setPath(path);
+ p.setFillColor(null);
+ applyStroke(p);
+ if (_paint instanceof Color) {
+ p.setStrokeStyle((Color)_paint);
+ }
+ }
+
+ /**
+ * Renders the text specified by the specified <code>String</code>,
+ * using the current text attribute state in the <code>Graphics2D</code> context.
+ * The baseline of the first character is at position
+ * (<i>x</i>, <i>y</i>) in the User Space.
+ * The rendering attributes applied include the <code>Clip</code>,
+ * <code>Transform</code>, <code>Paint</code>, <code>Font</code> and
+ * <code>Composite</code> attributes. For characters in script systems
+ * such as Hebrew and Arabic, the glyphs can be rendered from right to
+ * left, in which case the coordinate supplied is the location of the
+ * leftmost character on the baseline.
+ * @param s the <code>String</code> to be rendered
+ * @param x the x coordinate of the location where the
+ * <code>String</code> should be rendered
+ * @param y the y coordinate of the location where the
+ * <code>String</code> should be rendered
+ * @throws NullPointerException if <code>str</code> is
+ * <code>null</code>
+ * @see #setPaint
+ * @see java.awt.Graphics#setColor
+ * @see java.awt.Graphics#setFont
+ * @see #setTransform
+ * @see #setComposite
+ * @see #setClip
+ */
+ public void drawString(String s, float x, float y) {
+ TextBox<?,?> txt = _group.createTextBox();
+
+ TextRun rt = txt.getTextParagraphs().get(0).getTextRuns().get(0);
+ rt.setFontSize((double)_font.getSize());
+ rt.setFontFamily(_font.getFamily());
+
+ if (getColor() != null) rt.setFontColor(DrawPaint.createSolidPaint(getColor()));
+ if (_font.isBold()) rt.setBold(true);
+ if (_font.isItalic()) rt.setItalic(true);
+
+ txt.setText(s);
+
+ txt.setInsets(new Insets2D(0,0,0,0));
+ txt.setWordWrap(false);
+ txt.setHorizontalCentered(false);
+ txt.setVerticalAlignment(VerticalAlignment.MIDDLE);
+
+
+ TextLayout layout = new TextLayout(s, _font, getFontRenderContext());
+ float ascent = layout.getAscent();
+
+ float width = (float) Math.floor(layout.getAdvance());
+ /**
+ * Even if top and bottom margins are set to 0 PowerPoint
+ * always sets extra space between the text and its bounding box.
+ *
+ * The approximation height = ascent*2 works good enough in most cases
+ */
+ float height = ascent * 2;
+
+ /*
+ In powerpoint anchor of a shape is its top left corner.
+ Java graphics sets string coordinates by the baseline of the first character
+ so we need to shift up by the height of the textbox
+ */
+ y -= height / 2 + ascent / 2;
+
+ /*
+ In powerpoint anchor of a shape is its top left corner.
+ Java graphics sets string coordinates by the baseline of the first character
+ so we need to shift down by the height of the textbox
+ */
+ txt.setAnchor(new Rectangle((int)x, (int)y, (int)width, (int)height));
+ }
+
+ /**
+ * Fills the interior of a <code>Shape</code> using the settings of the
+ * <code>Graphics2D</code> context. The rendering attributes applied
+ * include the <code>Clip</code>, <code>Transform</code>,
+ * <code>Paint</code>, and <code>Composite</code>.
+ * @param shape the <code>Shape</code> to be filled
+ * @see #setPaint
+ * @see java.awt.Graphics#setColor
+ * @see #_transform
+ * @see #setTransform
+ * @see #setComposite
+ * @see #clip
+ * @see #setClip
+ */
+ public void fill(Shape shape){
+ GeneralPath path = new GeneralPath(_transform.createTransformedShape(shape));
+ FreeformShape<?,?> p = _group.createFreeform();
+ p.setPath(path);
+ applyPaint(p);
+ p.setStrokeStyle(); //Fills must be "No Line"
+ }
+
+ /**
+ * Translates the origin of the graphics context to the point
+ * (<i>x</i>, <i>y</i>) in the current coordinate system.
+ * Modifies this graphics context so that its new origin corresponds
+ * to the point (<i>x</i>, <i>y</i>) in this graphics context's
+ * original coordinate system. All coordinates used in subsequent
+ * rendering operations on this graphics context will be relative
+ * to this new origin.
+ * @param x the <i>x</i> coordinate.
+ * @param y the <i>y</i> coordinate.
+ */
+ public void translate(int x, int y){
+ _transform.translate(x, y);
+ }
+
+ /**
+ * Intersects the current <code>Clip</code> with the interior of the
+ * specified <code>Shape</code> and sets the <code>Clip</code> to the
+ * resulting intersection. The specified <code>Shape</code> is
+ * transformed with the current <code>Graphics2D</code>
+ * <code>Transform</code> before being intersected with the current
+ * <code>Clip</code>. This method is used to make the current
+ * <code>Clip</code> smaller.
+ * To make the <code>Clip</code> larger, use <code>setClip</code>.
+ * The <i>user clip</i> modified by this method is independent of the
+ * clipping associated with device bounds and visibility. If no clip has
+ * previously been set, or if the clip has been cleared using
+ * {@link java.awt.Graphics#setClip(Shape) setClip} with a
+ * <code>null</code> argument, the specified <code>Shape</code> becomes
+ * the new user clip.
+ * @param s the <code>Shape</code> to be intersected with the current
+ * <code>Clip</code>. If <code>s</code> is <code>null</code>,
+ * this method clears the current <code>Clip</code>.
+ */
+ public void clip(Shape s){
+ if (log.check(POILogger.WARN)) {
+ log.log(POILogger.WARN, "Not implemented");
+ }
+ }
+
+ /**
+ * Gets the current clipping area.
+ * This method returns the user clip, which is independent of the
+ * clipping associated with device bounds and window visibility.
+ * If no clip has previously been set, or if the clip has been
+ * cleared using <code>setClip(null)</code>, this method returns
+ * <code>null</code>.
+ * @return a <code>Shape</code> object representing the
+ * current clipping area, or <code>null</code> if
+ * no clip is set.
+ * @see java.awt.Graphics#getClipBounds()
+ * @see java.awt.Graphics#clipRect
+ * @see java.awt.Graphics#setClip(int, int, int, int)
+ * @see java.awt.Graphics#setClip(Shape)
+ * @since JDK1.1
+ */
+ public Shape getClip(){
+ if (log.check(POILogger.WARN)) {
+ log.log(POILogger.WARN, "Not implemented");
+ }
+ return null;
+ }
+
+ /**
+ * Concatenates the current <code>Graphics2D</code>
+ * <code>Transform</code> with a scaling transformation
+ * Subsequent rendering is resized according to the specified scaling
+ * factors relative to the previous scaling.
+ * This is equivalent to calling <code>transform(S)</code>, where S is an
+ * <code>AffineTransform</code> represented by the following matrix:
+ * <pre>
+ * [ sx 0 0 ]
+ * [ 0 sy 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ * @param sx the amount by which X coordinates in subsequent
+ * rendering operations are multiplied relative to previous
+ * rendering operations.
+ * @param sy the amount by which Y coordinates in subsequent
+ * rendering operations are multiplied relative to previous
+ * rendering operations.
+ */
+ public void scale(double sx, double sy){
+ _transform.scale(sx, sy);
+ }
+
+ /**
+ * Draws an outlined round-cornered rectangle using this graphics
+ * context's current color. The left and right edges of the rectangle
+ * are at <code>x</code> and <code>x + width</code>,
+ * respectively. The top and bottom edges of the rectangle are at
+ * <code>y</code> and <code>y + height</code>.
+ * @param x the <i>x</i> coordinate of the rectangle to be drawn.
+ * @param y the <i>y</i> coordinate of the rectangle to be drawn.
+ * @param width the width of the rectangle to be drawn.
+ * @param height the height of the rectangle to be drawn.
+ * @param arcWidth the horizontal diameter of the arc
+ * at the four corners.
+ * @param arcHeight the vertical diameter of the arc
+ * at the four corners.
+ * @see java.awt.Graphics#fillRoundRect
+ */
+ public void drawRoundRect(int x, int y, int width, int height,
+ int arcWidth, int arcHeight){
+ RoundRectangle2D rect = new RoundRectangle2D.Float(x, y, width, height, arcWidth, arcHeight);
+ draw(rect);
+ }
+
+ /**
+ * Draws the text given by the specified string, using this
+ * graphics context's current font and color. The baseline of the
+ * first character is at position (<i>x</i>, <i>y</i>) in this
+ * graphics context's coordinate system.
+ * @param str the string to be drawn.
+ * @param x the <i>x</i> coordinate.
+ * @param y the <i>y</i> coordinate.
+ * @see java.awt.Graphics#drawBytes
+ * @see java.awt.Graphics#drawChars
+ */
+ public void drawString(String str, int x, int y){
+ drawString(str, (float)x, (float)y);
+ }
+
+ /**
+ * Fills an oval bounded by the specified rectangle with the
+ * current color.
+ * @param x the <i>x</i> coordinate of the upper left corner
+ * of the oval to be filled.
+ * @param y the <i>y</i> coordinate of the upper left corner
+ * of the oval to be filled.
+ * @param width the width of the oval to be filled.
+ * @param height the height of the oval to be filled.
+ * @see java.awt.Graphics#drawOval
+ */
+ public void fillOval(int x, int y, int width, int height){
+ Ellipse2D oval = new Ellipse2D.Float(x, y, width, height);
+ fill(oval);
+ }
+
+ /**
+ * Fills the specified rounded corner rectangle with the current color.
+ * The left and right edges of the rectangle
+ * are at <code>x</code> and <code>x + width - 1</code>,
+ * respectively. The top and bottom edges of the rectangle are at
+ * <code>y</code> and <code>y + height - 1</code>.
+ * @param x the <i>x</i> coordinate of the rectangle to be filled.
+ * @param y the <i>y</i> coordinate of the rectangle to be filled.
+ * @param width the width of the rectangle to be filled.
+ * @param height the height of the rectangle to be filled.
+ * @param arcWidth the horizontal diameter
+ * of the arc at the four corners.
+ * @param arcHeight the vertical diameter
+ * of the arc at the four corners.
+ * @see java.awt.Graphics#drawRoundRect
+ */
+ public void fillRoundRect(int x, int y, int width, int height,
+ int arcWidth, int arcHeight){
+
+ RoundRectangle2D rect = new RoundRectangle2D.Float(x, y, width, height, arcWidth, arcHeight);
+ fill(rect);
+ }
+
+ /**
+ * Fills a circular or elliptical arc covering the specified rectangle.
+ * <p>
+ * The resulting arc begins at <code>startAngle</code> and extends
+ * for <code>arcAngle</code> degrees.
+ * Angles are interpreted such that 0 degrees
+ * is at the 3 o'clock position.
+ * A positive value indicates a counter-clockwise rotation
+ * while a negative value indicates a clockwise rotation.
+ * <p>
+ * The center of the arc is the center of the rectangle whose origin
+ * is (<i>x</i>, <i>y</i>) and whose size is specified by the
+ * <code>width</code> and <code>height</code> arguments.
+ * <p>
+ * The resulting arc covers an area
+ * <code>width + 1</code> pixels wide
+ * by <code>height + 1</code> pixels tall.
+ * <p>
+ * The angles are specified relative to the non-square extents of
+ * the bounding rectangle such that 45 degrees always falls on the
+ * line from the center of the ellipse to the upper right corner of
+ * the bounding rectangle. As a result, if the bounding rectangle is
+ * noticeably longer in one axis than the other, the angles to the
+ * start and end of the arc segment will be skewed farther along the
+ * longer axis of the bounds.
+ * @param x the <i>x</i> coordinate of the
+ * upper-left corner of the arc to be filled.
+ * @param y the <i>y</i> coordinate of the
+ * upper-left corner of the arc to be filled.
+ * @param width the width of the arc to be filled.
+ * @param height the height of the arc to be filled.
+ * @param startAngle the beginning angle.
+ * @param arcAngle the angular extent of the arc,
+ * relative to the start angle.
+ * @see java.awt.Graphics#drawArc
+ */
+ public void fillArc(int x, int y, int width, int height,
+ int startAngle, int arcAngle){
+ Arc2D arc = new Arc2D.Float(x, y, width, height, startAngle, arcAngle, Arc2D.PIE);
+ fill(arc);
+ }
+
+ /**
+ * Draws the outline of a circular or elliptical arc
+ * covering the specified rectangle.
+ * <p>
+ * The resulting arc begins at <code>startAngle</code> and extends
+ * for <code>arcAngle</code> degrees, using the current color.
+ * Angles are interpreted such that 0 degrees
+ * is at the 3 o'clock position.
+ * A positive value indicates a counter-clockwise rotation
+ * while a negative value indicates a clockwise rotation.
+ * <p>
+ * The center of the arc is the center of the rectangle whose origin
+ * is (<i>x</i>, <i>y</i>) and whose size is specified by the
+ * <code>width</code> and <code>height</code> arguments.
+ * <p>
+ * The resulting arc covers an area
+ * <code>width + 1</code> pixels wide
+ * by <code>height + 1</code> pixels tall.
+ * <p>
+ * The angles are specified relative to the non-square extents of
+ * the bounding rectangle such that 45 degrees always falls on the
+ * line from the center of the ellipse to the upper right corner of
+ * the bounding rectangle. As a result, if the bounding rectangle is
+ * noticeably longer in one axis than the other, the angles to the
+ * start and end of the arc segment will be skewed farther along the
+ * longer axis of the bounds.
+ * @param x the <i>x</i> coordinate of the
+ * upper-left corner of the arc to be drawn.
+ * @param y the <i>y</i> coordinate of the
+ * upper-left corner of the arc to be drawn.
+ * @param width the width of the arc to be drawn.
+ * @param height the height of the arc to be drawn.
+ * @param startAngle the beginning angle.
+ * @param arcAngle the angular extent of the arc,
+ * relative to the start angle.
+ * @see java.awt.Graphics#fillArc
+ */
+ public void drawArc(int x, int y, int width, int height,
+ int startAngle, int arcAngle) {
+ Arc2D arc = new Arc2D.Float(x, y, width, height, startAngle, arcAngle, Arc2D.OPEN);
+ draw(arc);
+ }
+
+
+ /**
+ * Draws a sequence of connected lines defined by
+ * arrays of <i>x</i> and <i>y</i> coordinates.
+ * Each pair of (<i>x</i>, <i>y</i>) coordinates defines a point.
+ * The figure is not closed if the first point
+ * differs from the last point.
+ * @param xPoints an array of <i>x</i> points
+ * @param yPoints an array of <i>y</i> points
+ * @param nPoints the total number of points
+ * @see java.awt.Graphics#drawPolygon(int[], int[], int)
+ * @since JDK1.1
+ */
+ public void drawPolyline(int[] xPoints, int[] yPoints,
+ int nPoints){
+ if(nPoints > 0){
+ GeneralPath path = new GeneralPath();
+ path.moveTo(xPoints[0], yPoints[0]);
+ for(int i=1; i<nPoints; i++)
+ path.lineTo(xPoints[i], yPoints[i]);
+
+ draw(path);
+ }
+ }
+
+ /**
+ * Draws the outline of an oval.
+ * The result is a circle or ellipse that fits within the
+ * rectangle specified by the <code>x</code>, <code>y</code>,
+ * <code>width</code>, and <code>height</code> arguments.
+ * <p>
+ * The oval covers an area that is
+ * <code>width + 1</code> pixels wide
+ * and <code>height + 1</code> pixels tall.
+ * @param x the <i>x</i> coordinate of the upper left
+ * corner of the oval to be drawn.
+ * @param y the <i>y</i> coordinate of the upper left
+ * corner of the oval to be drawn.
+ * @param width the width of the oval to be drawn.
+ * @param height the height of the oval to be drawn.
+ * @see java.awt.Graphics#fillOval
+ */
+ public void drawOval(int x, int y, int width, int height){
+ Ellipse2D oval = new Ellipse2D.Float(x, y, width, height);
+ draw(oval);
+ }
+
+ /**
+ * Draws as much of the specified image as is currently available.
+ * The image is drawn with its top-left corner at
+ * (<i>x</i>, <i>y</i>) in this graphics context's coordinate
+ * space. Transparent pixels are drawn in the specified
+ * background color.
+ * <p>
+ * This operation is equivalent to filling a rectangle of the
+ * width and height of the specified image with the given color and then
+ * drawing the image on top of it, but possibly more efficient.
+ * <p>
+ * This method returns immediately in all cases, even if the
+ * complete image has not yet been loaded, and it has not been dithered
+ * and converted for the current output device.
+ * <p>
+ * If the image has not yet been completely loaded, then
+ * <code>drawImage</code> returns <code>false</code>. As more of
+ * the image becomes available, the process that draws the image notifies
+ * the specified image observer.
+ * @param img the specified image to be drawn.
+ * @param x the <i>x</i> coordinate.
+ * @param y the <i>y</i> coordinate.
+ * @param bgcolor the background color to paint under the
+ * non-opaque portions of the image.
+ * @param observer object to be notified as more of
+ * the image is converted.
+ * @see java.awt.Image
+ * @see java.awt.image.ImageObserver
+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
+ */
+ public boolean drawImage(Image img, int x, int y,
+ Color bgcolor,
+ ImageObserver observer){
+ if (log.check(POILogger.WARN)) {
+ log.log(POILogger.WARN, "Not implemented");
+ }
+
+ return false;
+ }
+
+ /**
+ * Draws as much of the specified image as has already been scaled
+ * to fit inside the specified rectangle.
+ * <p>
+ * The image is drawn inside the specified rectangle of this
+ * graphics context's coordinate space, and is scaled if
+ * necessary. Transparent pixels are drawn in the specified
+ * background color.
+ * This operation is equivalent to filling a rectangle of the
+ * width and height of the specified image with the given color and then
+ * drawing the image on top of it, but possibly more efficient.
+ * <p>
+ * This method returns immediately in all cases, even if the
+ * entire image has not yet been scaled, dithered, and converted
+ * for the current output device.
+ * If the current output representation is not yet complete then
+ * <code>drawImage</code> returns <code>false</code>. As more of
+ * the image becomes available, the process that draws the image notifies
+ * the specified image observer.
+ * <p>
+ * A scaled version of an image will not necessarily be
+ * available immediately just because an unscaled version of the
+ * image has been constructed for this output device. Each size of
+ * the image may be cached separately and generated from the original
+ * data in a separate image production sequence.
+ * @param img the specified image to be drawn.
+ * @param x the <i>x</i> coordinate.
+ * @param y the <i>y</i> coordinate.
+ * @param width the width of the rectangle.
+ * @param height the height of the rectangle.
+ * @param bgcolor the background color to paint under the
+ * non-opaque portions of the image.
+ * @param observer object to be notified as more of
+ * the image is converted.
+ * @see java.awt.Image
+ * @see java.awt.image.ImageObserver
+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
+ */
+ public boolean drawImage(Image img, int x, int y,
+ int width, int height,
+ Color bgcolor,
+ ImageObserver observer){
+ if (log.check(POILogger.WARN)) {
+ log.log(POILogger.WARN, "Not implemented");
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Draws as much of the specified area of the specified image as is
+ * currently available, scaling it on the fly to fit inside the
+ * specified area of the destination drawable surface. Transparent pixels
+ * do not affect whatever pixels are already there.
+ * <p>
+ * This method returns immediately in all cases, even if the
+ * image area to be drawn has not yet been scaled, dithered, and converted
+ * for the current output device.
+ * If the current output representation is not yet complete then
+ * <code>drawImage</code> returns <code>false</code>. As more of
+ * the image becomes available, the process that draws the image notifies
+ * the specified image observer.
+ * <p>
+ * This method always uses the unscaled version of the image
+ * to render the scaled rectangle and performs the required
+ * scaling on the fly. It does not use a cached, scaled version
+ * of the image for this operation. Scaling of the image from source
+ * to destination is performed such that the first coordinate
+ * of the source rectangle is mapped to the first coordinate of
+ * the destination rectangle, and the second source coordinate is
+ * mapped to the second destination coordinate. The subimage is
+ * scaled and flipped as needed to preserve those mappings.
+ * @param img the specified image to be drawn
+ * @param dx1 the <i>x</i> coordinate of the first corner of the
+ * destination rectangle.
+ * @param dy1 the <i>y</i> coordinate of the first corner of the
+ * destination rectangle.
+ * @param dx2 the <i>x</i> coordinate of the second corner of the
+ * destination rectangle.
+ * @param dy2 the <i>y</i> coordinate of the second corner of the
+ * destination rectangle.
+ * @param sx1 the <i>x</i> coordinate of the first corner of the
+ * source rectangle.
+ * @param sy1 the <i>y</i> coordinate of the first corner of the
+ * source rectangle.
+ * @param sx2 the <i>x</i> coordinate of the second corner of the
+ * source rectangle.
+ * @param sy2 the <i>y</i> coordinate of the second corner of the
+ * source rectangle.
+ * @param observer object to be notified as more of the image is
+ * scaled and converted.
+ * @see java.awt.Image
+ * @see java.awt.image.ImageObserver
+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
+ * @since JDK1.1
+ */
+ public boolean drawImage(Image img,
+ int dx1, int dy1, int dx2, int dy2,
+ int sx1, int sy1, int sx2, int sy2,
+ ImageObserver observer){
+ if (log.check(POILogger.WARN)) {
+ log.log(POILogger.WARN, "Not implemented");
+ }
+ return false;
+ }
+
+ /**
+ * Draws as much of the specified area of the specified image as is
+ * currently available, scaling it on the fly to fit inside the
+ * specified area of the destination drawable surface.
+ * <p>
+ * Transparent pixels are drawn in the specified background color.
+ * This operation is equivalent to filling a rectangle of the
+ * width and height of the specified image with the given color and then
+ * drawing the image on top of it, but possibly more efficient.
+ * <p>
+ * This method returns immediately in all cases, even if the
+ * image area to be drawn has not yet been scaled, dithered, and converted
+ * for the current output device.
+ * If the current output representation is not yet complete then
+ * <code>drawImage</code> returns <code>false</code>. As more of
+ * the image becomes available, the process that draws the image notifies
+ * the specified image observer.
+ * <p>
+ * This method always uses the unscaled version of the image
+ * to render the scaled rectangle and performs the required
+ * scaling on the fly. It does not use a cached, scaled version
+ * of the image for this operation. Scaling of the image from source
+ * to destination is performed such that the first coordinate
+ * of the source rectangle is mapped to the first coordinate of
+ * the destination rectangle, and the second source coordinate is
+ * mapped to the second destination coordinate. The subimage is
+ * scaled and flipped as needed to preserve those mappings.
+ * @param img the specified image to be drawn
+ * @param dx1 the <i>x</i> coordinate of the first corner of the
+ * destination rectangle.
+ * @param dy1 the <i>y</i> coordinate of the first corner of the
+ * destination rectangle.
+ * @param dx2 the <i>x</i> coordinate of the second corner of the
+ * destination rectangle.
+ * @param dy2 the <i>y</i> coordinate of the second corner of the
+ * destination rectangle.
+ * @param sx1 the <i>x</i> coordinate of the first corner of the
+ * source rectangle.
+ * @param sy1 the <i>y</i> coordinate of the first corner of the
+ * source rectangle.
+ * @param sx2 the <i>x</i> coordinate of the second corner of the
+ * source rectangle.
+ * @param sy2 the <i>y</i> coordinate of the second corner of the
+ * source rectangle.
+ * @param bgcolor the background color to paint under the
+ * non-opaque portions of the image.
+ * @param observer object to be notified as more of the image is
+ * scaled and converted.
+ * @see java.awt.Image
+ * @see java.awt.image.ImageObserver
+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
+ * @since JDK1.1
+ */
+ public boolean drawImage(Image img,
+ int dx1, int dy1, int dx2, int dy2,
+ int sx1, int sy1, int sx2, int sy2,
+ Color bgcolor,
+ ImageObserver observer){
+ if (log.check(POILogger.WARN)) {
+ log.log(POILogger.WARN, "Not implemented");
+ }
+ return false;
+ }
+
+ /**
+ * Draws as much of the specified image as is currently available.
+ * The image is drawn with its top-left corner at
+ * (<i>x</i>, <i>y</i>) in this graphics context's coordinate
+ * space. Transparent pixels in the image do not affect whatever
+ * pixels are already there.
+ * <p>
+ * This method returns immediately in all cases, even if the
+ * complete image has not yet been loaded, and it has not been dithered
+ * and converted for the current output device.
+ * <p>
+ * If the image has completely loaded and its pixels are
+ * no longer being changed, then
+ * <code>drawImage</code> returns <code>true</code>.
+ * Otherwise, <code>drawImage</code> returns <code>false</code>
+ * and as more of
+ * the image becomes available
+ * or it is time to draw another frame of animation,
+ * the process that loads the image notifies
+ * the specified image observer.
+ * @param img the specified image to be drawn. This method does
+ * nothing if <code>img</code> is null.
+ * @param x the <i>x</i> coordinate.
+ * @param y the <i>y</i> coordinate.
+ * @param observer object to be notified as more of
+ * the image is converted.
+ * @return <code>false</code> if the image pixels are still changing;
+ * <code>true</code> otherwise.
+ * @see java.awt.Image
+ * @see java.awt.image.ImageObserver
+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
+ */
+ public boolean drawImage(Image img, int x, int y,
+ ImageObserver observer) {
+ if (log.check(POILogger.WARN)) {
+ log.log(POILogger.WARN, "Not implemented");
+ }
+ return false;
+ }
+
+ /**
+ * Disposes of this graphics context and releases
+ * any system resources that it is using.
+ * A <code>Graphics</code> object cannot be used after
+ * <code>dispose</code>has been called.
+ * <p>
+ * When a Java program runs, a large number of <code>Graphics</code>
+ * objects can be created within a short time frame.
+ * Although the finalization process of the garbage collector
+ * also disposes of the same system resources, it is preferable
+ * to manually free the associated resources by calling this
+ * method rather than to rely on a finalization process which
+ * may not run to completion for a long period of time.
+ * <p>
+ * Graphics objects which are provided as arguments to the
+ * <code>paint</code> and <code>update</code> methods
+ * of components are automatically released by the system when
+ * those methods return. For efficiency, programmers should
+ * call <code>dispose</code> when finished using
+ * a <code>Graphics</code> object only if it was created
+ * directly from a component or another <code>Graphics</code> object.
+ * @see java.awt.Graphics#finalize
+ * @see java.awt.Component#paint
+ * @see java.awt.Component#update
+ * @see java.awt.Component#getGraphics
+ * @see java.awt.Graphics#create
+ */
+ public void dispose() {
+ ;
+ }
+
+ /**
+ * Draws a line, using the current color, between the points
+ * <code>(x1, y1)</code> and <code>(x2, y2)</code>
+ * in this graphics context's coordinate system.
+ * @param x1 the first point's <i>x</i> coordinate.
+ * @param y1 the first point's <i>y</i> coordinate.
+ * @param x2 the second point's <i>x</i> coordinate.
+ * @param y2 the second point's <i>y</i> coordinate.
+ */
+ public void drawLine(int x1, int y1, int x2, int y2){
+ Line2D line = new Line2D.Float(x1, y1, x2, y2);
+ draw(line);
+ }
+
+ /**
+ * Fills a closed polygon defined by
+ * arrays of <i>x</i> and <i>y</i> coordinates.
+ * <p>
+ * This method draws the polygon defined by <code>nPoint</code> line
+ * segments, where the first <code>nPoint - 1</code>
+ * line segments are line segments from
+ * <code>(xPoints[i - 1], yPoints[i - 1])</code>
+ * to <code>(xPoints[i], yPoints[i])</code>, for
+ * 1 ≤ <i>i</i> ≤ <code>nPoints</code>.
+ * The figure is automatically closed by drawing a line connecting
+ * the final point to the first point, if those points are different.
+ * <p>
+ * The area inside the polygon is defined using an
+ * even-odd fill rule, also known as the alternating rule.
+ * @param xPoints a an array of <code>x</code> coordinates.
+ * @param yPoints a an array of <code>y</code> coordinates.
+ * @param nPoints a the total number of points.
+ * @see java.awt.Graphics#drawPolygon(int[], int[], int)
+ */
+ public void fillPolygon(int[] xPoints, int[] yPoints,
+ int nPoints){
+ java.awt.Polygon polygon = new java.awt.Polygon(xPoints, yPoints, nPoints);
+ fill(polygon);
+ }
+
+ /**
+ * Fills the specified rectangle.
+ * The left and right edges of the rectangle are at
+ * <code>x</code> and <code>x + width - 1</code>.
+ * The top and bottom edges are at
+ * <code>y</code> and <code>y + height - 1</code>.
+ * The resulting rectangle covers an area
+ * <code>width</code> pixels wide by
+ * <code>height</code> pixels tall.
+ * The rectangle is filled using the graphics context's current color.
+ * @param x the <i>x</i> coordinate
+ * of the rectangle to be filled.
+ * @param y the <i>y</i> coordinate
+ * of the rectangle to be filled.
+ * @param width the width of the rectangle to be filled.
+ * @param height the height of the rectangle to be filled.
+ * @see java.awt.Graphics#clearRect
+ * @see java.awt.Graphics#drawRect
+ */
+ public void fillRect(int x, int y, int width, int height){
+ Rectangle rect = new Rectangle(x, y, width, height);
+ fill(rect);
+ }
+
+ /**
+ * Draws the outline of the specified rectangle.
+ * The left and right edges of the rectangle are at
+ * <code>x</code> and <code>x + width</code>.
+ * The top and bottom edges are at
+ * <code>y</code> and <code>y + height</code>.
+ * The rectangle is drawn using the graphics context's current color.
+ * @param x the <i>x</i> coordinate
+ * of the rectangle to be drawn.
+ * @param y the <i>y</i> coordinate
+ * of the rectangle to be drawn.
+ * @param width the width of the rectangle to be drawn.
+ * @param height the height of the rectangle to be drawn.
+ * @see java.awt.Graphics#fillRect
+ * @see java.awt.Graphics#clearRect
+ */
+ public void drawRect(int x, int y, int width, int height) {
+ Rectangle rect = new Rectangle(x, y, width, height);
+ draw(rect);
+ }
+
+ /**
+ * Draws a closed polygon defined by
+ * arrays of <i>x</i> and <i>y</i> coordinates.
+ * Each pair of (<i>x</i>, <i>y</i>) coordinates defines a point.
+ * <p>
+ * This method draws the polygon defined by <code>nPoint</code> line
+ * segments, where the first <code>nPoint - 1</code>
+ * line segments are line segments from
+ * <code>(xPoints[i - 1], yPoints[i - 1])</code>
+ * to <code>(xPoints[i], yPoints[i])</code>, for
+ * 1 ≤ <i>i</i> ≤ <code>nPoints</code>.
+ * The figure is automatically closed by drawing a line connecting
+ * the final point to the first point, if those points are different.
+ * @param xPoints a an array of <code>x</code> coordinates.
+ * @param yPoints a an array of <code>y</code> coordinates.
+ * @param nPoints a the total number of points.
+ * @see java.awt.Graphics#fillPolygon(int[],int[],int)
+ * @see java.awt.Graphics#drawPolyline
+ */
+ public void drawPolygon(int[] xPoints, int[] yPoints,
+ int nPoints){
+ java.awt.Polygon polygon = new java.awt.Polygon(xPoints, yPoints, nPoints);
+ draw(polygon);
+ }
+
+ /**
+ * Intersects the current clip with the specified rectangle.
+ * The resulting clipping area is the intersection of the current
+ * clipping area and the specified rectangle. If there is no
+ * current clipping area, either because the clip has never been
+ * set, or the clip has been cleared using <code>setClip(null)</code>,
+ * the specified rectangle becomes the new clip.
+ * This method sets the user clip, which is independent of the
+ * clipping associated with device bounds and window visibility.
+ * This method can only be used to make the current clip smaller.
+ * To set the current clip larger, use any of the setClip methods.
+ * Rendering operations have no effect outside of the clipping area.
+ * @param x the x coordinate of the rectangle to intersect the clip with
+ * @param y the y coordinate of the rectangle to intersect the clip with
+ * @param width the width of the rectangle to intersect the clip with
+ * @param height the height of the rectangle to intersect the clip with
+ * @see #setClip(int, int, int, int)
+ * @see #setClip(Shape)
+ */
+ public void clipRect(int x, int y, int width, int height){
+ clip(new Rectangle(x, y, width, height));
+ }
+
+ /**
+ * Sets the current clipping area to an arbitrary clip shape.
+ * Not all objects that implement the <code>Shape</code>
+ * interface can be used to set the clip. The only
+ * <code>Shape</code> objects that are guaranteed to be
+ * supported are <code>Shape</code> objects that are
+ * obtained via the <code>getClip</code> method and via
+ * <code>Rectangle</code> objects. This method sets the
+ * user clip, which is independent of the clipping associated
+ * with device bounds and window visibility.
+ * @param clip the <code>Shape</code> to use to set the clip
+ * @see java.awt.Graphics#getClip()
+ * @see java.awt.Graphics#clipRect
+ * @see java.awt.Graphics#setClip(int, int, int, int)
+ * @since JDK1.1
+ */
+ public void setClip(Shape clip) {
+ if (log.check(POILogger.WARN)) {
+ log.log(POILogger.WARN, "Not implemented");
+ }
+ }
+
+ /**
+ * Returns the bounding rectangle of the current clipping area.
+ * This method refers to the user clip, which is independent of the
+ * clipping associated with device bounds and window visibility.
+ * If no clip has previously been set, or if the clip has been
+ * cleared using <code>setClip(null)</code>, this method returns
+ * <code>null</code>.
+ * The coordinates in the rectangle are relative to the coordinate
+ * system origin of this graphics context.
+ * @return the bounding rectangle of the current clipping area,
+ * or <code>null</code> if no clip is set.
+ * @see java.awt.Graphics#getClip
+ * @see java.awt.Graphics#clipRect
+ * @see java.awt.Graphics#setClip(int, int, int, int)
+ * @see java.awt.Graphics#setClip(Shape)
+ * @since JDK1.1
+ */
+ public Rectangle getClipBounds(){
+ Shape c = getClip();
+ if (c==null) {
+ return null;
+ }
+ return c.getBounds();
+ }
+
+ /**
+ * Draws the text given by the specified iterator, using this
+ * graphics context's current color. The iterator has to specify a font
+ * for each character. The baseline of the
+ * first character is at position (<i>x</i>, <i>y</i>) in this
+ * graphics context's coordinate system.
+ * @param iterator the iterator whose text is to be drawn
+ * @param x the <i>x</i> coordinate.
+ * @param y the <i>y</i> coordinate.
+ * @see java.awt.Graphics#drawBytes
+ * @see java.awt.Graphics#drawChars
+ */
+ public void drawString(AttributedCharacterIterator iterator,
+ int x, int y){
+ drawString(iterator, (float)x, (float)y);
+ }
+
+ /**
+ * Clears the specified rectangle by filling it with the background
+ * color of the current drawing surface. This operation does not
+ * use the current paint mode.
+ * <p>
+ * Beginning with Java 1.1, the background color
+ * of offscreen images may be system dependent. Applications should
+ * use <code>setColor</code> followed by <code>fillRect</code> to
+ * ensure that an offscreen image is cleared to a specific color.
+ * @param x the <i>x</i> coordinate of the rectangle to clear.
+ * @param y the <i>y</i> coordinate of the rectangle to clear.
+ * @param width the width of the rectangle to clear.
+ * @param height the height of the rectangle to clear.
+ * @see java.awt.Graphics#fillRect(int, int, int, int)
+ * @see java.awt.Graphics#drawRect
+ * @see java.awt.Graphics#setColor(java.awt.Color)
+ * @see java.awt.Graphics#setPaintMode
+ * @see java.awt.Graphics#setXORMode(java.awt.Color)
+ */
+ public void clearRect(int x, int y, int width, int height) {
+ Paint paint = getPaint();
+ setColor(getBackground());
+ fillRect(x, y, width, height);
+ setPaint(paint);
+ }
+
+ public void copyArea(int x, int y, int width, int height, int dx, int dy) {
+ ;
+ }
+
+ /**
+ * Sets the current clip to the rectangle specified by the given
+ * coordinates. This method sets the user clip, which is
+ * independent of the clipping associated with device bounds
+ * and window visibility.
+ * Rendering operations have no effect outside of the clipping area.
+ * @param x the <i>x</i> coordinate of the new clip rectangle.
+ * @param y the <i>y</i> coordinate of the new clip rectangle.
+ * @param width the width of the new clip rectangle.
+ * @param height the height of the new clip rectangle.
+ * @see java.awt.Graphics#clipRect
+ * @see java.awt.Graphics#setClip(Shape)
+ * @since JDK1.1
+ */
+ public void setClip(int x, int y, int width, int height){
+ setClip(new Rectangle(x, y, width, height));
+ }
+
+ /**
+ * Concatenates the current <code>Graphics2D</code>
+ * <code>Transform</code> with a rotation transform.
+ * Subsequent rendering is rotated by the specified radians relative
+ * to the previous origin.
+ * This is equivalent to calling <code>transform(R)</code>, where R is an
+ * <code>AffineTransform</code> represented by the following matrix:
+ * <pre>
+ * [ cos(theta) -sin(theta) 0 ]
+ * [ sin(theta) cos(theta) 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ * Rotating with a positive angle theta rotates points on the positive
+ * x axis toward the positive y axis.
+ * @param theta the angle of rotation in radians
+ */
+ public void rotate(double theta){
+ _transform.rotate(theta);
+ }
+
+ /**
+ * Concatenates the current <code>Graphics2D</code>
+ * <code>Transform</code> with a translated rotation
+ * transform. Subsequent rendering is transformed by a transform
+ * which is constructed by translating to the specified location,
+ * rotating by the specified radians, and translating back by the same
+ * amount as the original translation. This is equivalent to the
+ * following sequence of calls:
+ * <pre>
+ * translate(x, y);
+ * rotate(theta);
+ * translate(-x, -y);
+ * </pre>
+ * Rotating with a positive angle theta rotates points on the positive
+ * x axis toward the positive y axis.
+ * @param theta the angle of rotation in radians
+ * @param x x coordinate of the origin of the rotation
+ * @param y y coordinate of the origin of the rotation
+ */
+ public void rotate(double theta, double x, double y){
+ _transform.rotate(theta, x, y);
+ }
+
+ /**
+ * Concatenates the current <code>Graphics2D</code>
+ * <code>Transform</code> with a shearing transform.
+ * Subsequent renderings are sheared by the specified
+ * multiplier relative to the previous position.
+ * This is equivalent to calling <code>transform(SH)</code>, where SH
+ * is an <code>AffineTransform</code> represented by the following
+ * matrix:
+ * <pre>
+ * [ 1 shx 0 ]
+ * [ shy 1 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ * @param shx the multiplier by which coordinates are shifted in
+ * the positive X axis direction as a function of their Y coordinate
+ * @param shy the multiplier by which coordinates are shifted in
+ * the positive Y axis direction as a function of their X coordinate
+ */
+ public void shear(double shx, double shy){
+ _transform.shear(shx, shy);
+ }
+
+ /**
+ * Get the rendering context of the <code>Font</code> within this
+ * <code>Graphics2D</code> context.
+ * The {@link FontRenderContext}
+ * encapsulates application hints such as anti-aliasing and
+ * fractional metrics, as well as target device specific information
+ * such as dots-per-inch. This information should be provided by the
+ * application when using objects that perform typographical
+ * formatting, such as <code>Font</code> and
+ * <code>TextLayout</code>. This information should also be provided
+ * by applications that perform their own layout and need accurate
+ * measurements of various characteristics of glyphs such as advance
+ * and line height when various rendering hints have been applied to
+ * the text rendering.
+ *
+ * @return a reference to an instance of FontRenderContext.
+ * @see java.awt.font.FontRenderContext
+ * @see java.awt.Font#createGlyphVector(FontRenderContext,char[])
+ * @see java.awt.font.TextLayout
+ * @since JDK1.2
+ */
+ public FontRenderContext getFontRenderContext() {
+ boolean isAntiAliased = RenderingHints.VALUE_TEXT_ANTIALIAS_ON.equals(
+ getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING));
+ boolean usesFractionalMetrics = RenderingHints.VALUE_FRACTIONALMETRICS_ON.equals(
+ getRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS));
+
+
+ return new FontRenderContext(new AffineTransform(), isAntiAliased, usesFractionalMetrics);
+ }
+
+ /**
+ * Composes an <code>AffineTransform</code> object with the
+ * <code>Transform</code> in this <code>Graphics2D</code> according
+ * to the rule last-specified-first-applied. If the current
+ * <code>Transform</code> is Cx, the result of composition
+ * with Tx is a new <code>Transform</code> Cx'. Cx' becomes the
+ * current <code>Transform</code> for this <code>Graphics2D</code>.
+ * Transforming a point p by the updated <code>Transform</code> Cx' is
+ * equivalent to first transforming p by Tx and then transforming
+ * the result by the original <code>Transform</code> Cx. In other
+ * words, Cx'(p) = Cx(Tx(p)). A copy of the Tx is made, if necessary,
+ * so further modifications to Tx do not affect rendering.
+ * @param Tx the <code>AffineTransform</code> object to be composed with
+ * the current <code>Transform</code>
+ * @see #setTransform
+ * @see AffineTransform
+ */
+ public void transform(AffineTransform Tx) {
+ _transform.concatenate(Tx);
+ }
+
+ /**
+ * Renders a <code>BufferedImage</code> that is
+ * filtered with a
+ * {@link BufferedImageOp}.
+ * The rendering attributes applied include the <code>Clip</code>,
+ * <code>Transform</code>
+ * and <code>Composite</code> attributes. This is equivalent to:
+ * <pre>
+ * img1 = op.filter(img, null);
+ * drawImage(img1, new AffineTransform(1f,0f,0f,1f,x,y), null);
+ * </pre>
+ * @param img the <code>BufferedImage</code> to be rendered
+ * @param op the filter to be applied to the image before rendering
+ * @param x the x coordinate in user space where the image is rendered
+ * @param y the y coordinate in user space where the image is rendered
+ * @see #_transform
+ * @see #setTransform
+ * @see #setComposite
+ * @see #clip
+ * @see #setClip(Shape)
+ */
+ public void drawImage(BufferedImage img,
+ BufferedImageOp op,
+ int x,
+ int y){
+ img = op.filter(img, null);
+ drawImage(img, x, y, null);
+ }
+
+ /**
+ * Sets the background color for the <code>Graphics2D</code> context.
+ * The background color is used for clearing a region.
+ * When a <code>Graphics2D</code> is constructed for a
+ * <code>Component</code>, the background color is
+ * inherited from the <code>Component</code>. Setting the background color
+ * in the <code>Graphics2D</code> context only affects the subsequent
+ * <code>clearRect</code> calls and not the background color of the
+ * <code>Component</code>. To change the background
+ * of the <code>Component</code>, use appropriate methods of
+ * the <code>Component</code>.
+ * @param color the background color that isused in
+ * subsequent calls to <code>clearRect</code>
+ * @see #getBackground
+ * @see java.awt.Graphics#clearRect
+ */
+ public void setBackground(Color color) {
+ if(color == null)
+ return;
+
+ _background = color;
+ }
+
+ /**
+ * Returns the background color used for clearing a region.
+ * @return the current <code>Graphics2D</code> <code>Color</code>,
+ * which defines the background color.
+ * @see #setBackground
+ */
+ public Color getBackground(){
+ return _background;
+ }
+
+ /**
+ * Sets the <code>Composite</code> for the <code>Graphics2D</code> context.
+ * The <code>Composite</code> is used in all drawing methods such as
+ * <code>drawImage</code>, <code>drawString</code>, <code>draw</code>,
+ * and <code>fill</code>. It specifies how new pixels are to be combined
+ * with the existing pixels on the graphics device during the rendering
+ * process.
+ * <p>If this <code>Graphics2D</code> context is drawing to a
+ * <code>Component</code> on the display screen and the
+ * <code>Composite</code> is a custom object rather than an
+ * instance of the <code>AlphaComposite</code> class, and if
+ * there is a security manager, its <code>checkPermission</code>
+ * method is called with an <code>AWTPermission("readDisplayPixels")</code>
+ * permission.
+ *
+ * @param comp the <code>Composite</code> object to be used for rendering
+ * @throws SecurityException
+ * if a custom <code>Composite</code> object is being
+ * used to render to the screen and a security manager
+ * is set and its <code>checkPermission</code> method
+ * does not allow the operation.
+ * @see java.awt.Graphics#setXORMode
+ * @see java.awt.Graphics#setPaintMode
+ * @see java.awt.AlphaComposite
+ */
+ public void setComposite(Composite comp){
+ if (log.check(POILogger.WARN)) {
+ log.log(POILogger.WARN, "Not implemented");
+ }
+ }
+
+ /**
+ * Returns the current <code>Composite</code> in the
+ * <code>Graphics2D</code> context.
+ * @return the current <code>Graphics2D</code> <code>Composite</code>,
+ * which defines a compositing style.
+ * @see #setComposite
+ */
+ public Composite getComposite(){
+ if (log.check(POILogger.WARN)) {
+ log.log(POILogger.WARN, "Not implemented");
+ }
+ return null;
+ }
+
+ /**
+ * Returns the value of a single preference for the rendering algorithms.
+ * Hint categories include controls for rendering quality and overall
+ * time/quality trade-off in the rendering process. Refer to the
+ * <code>RenderingHints</code> class for definitions of some common
+ * keys and values.
+ * @param hintKey the key corresponding to the hint to get.
+ * @return an object representing the value for the specified hint key.
+ * Some of the keys and their associated values are defined in the
+ * <code>RenderingHints</code> class.
+ * @see RenderingHints
+ */
+ public Object getRenderingHint(RenderingHints.Key hintKey){
+ return _hints.get(hintKey);
+ }
+
+ /**
+ * Sets the value of a single preference for the rendering algorithms.
+ * Hint categories include controls for rendering quality and overall
+ * time/quality trade-off in the rendering process. Refer to the
+ * <code>RenderingHints</code> class for definitions of some common
+ * keys and values.
+ * @param hintKey the key of the hint to be set.
+ * @param hintValue the value indicating preferences for the specified
+ * hint category.
+ * @see RenderingHints
+ */
+ public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue){
+ _hints.put(hintKey, hintValue);
+ }
+
+
+ /**
+ * Renders the text of the specified
+ * {@link GlyphVector} using
+ * the <code>Graphics2D</code> context's rendering attributes.
+ * The rendering attributes applied include the <code>Clip</code>,
+ * <code>Transform</code>, <code>Paint</code>, and
+ * <code>Composite</code> attributes. The <code>GlyphVector</code>
+ * specifies individual glyphs from a {@link Font}.
+ * The <code>GlyphVector</code> can also contain the glyph positions.
+ * This is the fastest way to render a set of characters to the
+ * screen.
+ *
+ * @param g the <code>GlyphVector</code> to be rendered
+ * @param x the x position in user space where the glyphs should be
+ * rendered
+ * @param y the y position in user space where the glyphs should be
+ * rendered
+ *
+ * @see java.awt.Font#createGlyphVector(FontRenderContext, char[])
+ * @see java.awt.font.GlyphVector
+ * @see #setPaint
+ * @see java.awt.Graphics#setColor
+ * @see #setTransform
+ * @see #setComposite
+ * @see #setClip(Shape)
+ */
+ public void drawGlyphVector(GlyphVector g, float x, float y) {
+ Shape glyphOutline = g.getOutline(x, y);
+ fill(glyphOutline);
+ }
+
+ /**
+ * Returns the device configuration associated with this
+ * <code>Graphics2D</code>.
+ * @return the device configuration
+ */
+ public GraphicsConfiguration getDeviceConfiguration() {
+ return GraphicsEnvironment.getLocalGraphicsEnvironment().
+ getDefaultScreenDevice().getDefaultConfiguration();
+ }
+
+ /**
+ * Sets the values of an arbitrary number of preferences for the
+ * rendering algorithms.
+ * Only values for the rendering hints that are present in the
+ * specified <code>Map</code> object are modified.
+ * All other preferences not present in the specified
+ * object are left unmodified.
+ * Hint categories include controls for rendering quality and
+ * overall time/quality trade-off in the rendering process.
+ * Refer to the <code>RenderingHints</code> class for definitions of
+ * some common keys and values.
+ * @param hints the rendering hints to be set
+ * @see RenderingHints
+ */
+ public void addRenderingHints(Map<?,?> hints){
+ this._hints.putAll(hints);
+ }
+
+ /**
+ * Concatenates the current
+ * <code>Graphics2D</code> <code>Transform</code>
+ * with a translation transform.
+ * Subsequent rendering is translated by the specified
+ * distance relative to the previous position.
+ * This is equivalent to calling transform(T), where T is an
+ * <code>AffineTransform</code> represented by the following matrix:
+ * <pre>
+ * [ 1 0 tx ]
+ * [ 0 1 ty ]
+ * [ 0 0 1 ]
+ * </pre>
+ * @param tx the distance to translate along the x-axis
+ * @param ty the distance to translate along the y-axis
+ */
+ public void translate(double tx, double ty){
+ _transform.translate(tx, ty);
+ }
+
+ /**
+ * Renders the text of the specified iterator, using the
+ * <code>Graphics2D</code> context's current <code>Paint</code>. The
+ * iterator must specify a font
+ * for each character. The baseline of the
+ * first character is at position (<i>x</i>, <i>y</i>) in the
+ * User Space.
+ * The rendering attributes applied include the <code>Clip</code>,
+ * <code>Transform</code>, <code>Paint</code>, and
+ * <code>Composite</code> attributes.
+ * For characters in script systems such as Hebrew and Arabic,
+ * the glyphs can be rendered from right to left, in which case the
+ * coordinate supplied is the location of the leftmost character
+ * on the baseline.
+ * @param iterator the iterator whose text is to be rendered
+ * @param x the x coordinate where the iterator's text is to be
+ * rendered
+ * @param y the y coordinate where the iterator's text is to be
+ * rendered
+ * @see #setPaint
+ * @see java.awt.Graphics#setColor
+ * @see #setTransform
+ * @see #setComposite
+ * @see #setClip
+ */
+ public void drawString(AttributedCharacterIterator iterator, float x, float y) {
+ if (log.check(POILogger.WARN)) {
+ log.log(POILogger.WARN, "Not implemented");
+ }
+ }
+
+ /**
+ * Checks whether or not the specified <code>Shape</code> intersects
+ * the specified {@link Rectangle}, which is in device
+ * space. If <code>onStroke</code> is false, this method checks
+ * whether or not the interior of the specified <code>Shape</code>
+ * intersects the specified <code>Rectangle</code>. If
+ * <code>onStroke</code> is <code>true</code>, this method checks
+ * whether or not the <code>Stroke</code> of the specified
+ * <code>Shape</code> outline intersects the specified
+ * <code>Rectangle</code>.
+ * The rendering attributes taken into account include the
+ * <code>Clip</code>, <code>Transform</code>, and <code>Stroke</code>
+ * attributes.
+ * @param rect the area in device space to check for a hit
+ * @param s the <code>Shape</code> to check for a hit
+ * @param onStroke flag used to choose between testing the
+ * stroked or the filled shape. If the flag is <code>true</code>, the
+ * <code>Stroke</code> oultine is tested. If the flag is
+ * <code>false</code>, the filled <code>Shape</code> is tested.
+ * @return <code>true</code> if there is a hit; <code>false</code>
+ * otherwise.
+ * @see #setStroke
+ * @see #fill(Shape)
+ * @see #draw(Shape)
+ * @see #_transform
+ * @see #setTransform
+ * @see #clip
+ * @see #setClip(Shape)
+ */
+ public boolean hit(Rectangle rect,
+ Shape s,
+ boolean onStroke){
+ if (onStroke) {
+ s = getStroke().createStrokedShape(s);
+ }
+
+ s = getTransform().createTransformedShape(s);
+
+ return s.intersects(rect);
+ }
+
+ /**
+ * Gets the preferences for the rendering algorithms. Hint categories
+ * include controls for rendering quality and overall time/quality
+ * trade-off in the rendering process.
+ * Returns all of the hint key/value pairs that were ever specified in
+ * one operation. Refer to the
+ * <code>RenderingHints</code> class for definitions of some common
+ * keys and values.
+ * @return a reference to an instance of <code>RenderingHints</code>
+ * that contains the current preferences.
+ * @see RenderingHints
+ */
+ public RenderingHints getRenderingHints(){
+ return _hints;
+ }
+
+ /**
+ * Replaces the values of all preferences for the rendering
+ * algorithms with the specified <code>hints</code>.
+ * The existing values for all rendering hints are discarded and
+ * the new set of known hints and values are initialized from the
+ * specified {@link Map} object.
+ * Hint categories include controls for rendering quality and
+ * overall time/quality trade-off in the rendering process.
+ * Refer to the <code>RenderingHints</code> class for definitions of
+ * some common keys and values.
+ * @param hints the rendering hints to be set
+ * @see RenderingHints
+ */
+ public void setRenderingHints(Map<?,?> hints){
+ this._hints = new RenderingHints(null);
+ this._hints.putAll(hints);
+ }
+
+ /**
+ * Renders an image, applying a transform from image space into user space
+ * before drawing.
+ * The transformation from user space into device space is done with
+ * the current <code>Transform</code> in the <code>Graphics2D</code>.
+ * The specified transformation is applied to the image before the
+ * transform attribute in the <code>Graphics2D</code> context is applied.
+ * The rendering attributes applied include the <code>Clip</code>,
+ * <code>Transform</code>, and <code>Composite</code> attributes.
+ * Note that no rendering is done if the specified transform is
+ * noninvertible.
+ * @param img the <code>Image</code> to be rendered
+ * @param xform the transformation from image space into user space
+ * @param obs the {@link ImageObserver}
+ * to be notified as more of the <code>Image</code>
+ * is converted
+ * @return <code>true</code> if the <code>Image</code> is
+ * fully loaded and completely rendered;
+ * <code>false</code> if the <code>Image</code> is still being loaded.
+ * @see #_transform
+ * @see #setTransform
+ * @see #setComposite
+ * @see #clip
+ * @see #setClip(Shape)
+ */
+ public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) {
+ if (log.check(POILogger.WARN)) {
+ log.log(POILogger.WARN, "Not implemented");
+ }
+ return false;
+ }
+
+ /**
+ * Draws as much of the specified image as has already been scaled
+ * to fit inside the specified rectangle.
+ * <p>
+ * The image is drawn inside the specified rectangle of this
+ * graphics context's coordinate space, and is scaled if
+ * necessary. Transparent pixels do not affect whatever pixels
+ * are already there.
+ * <p>
+ * This method returns immediately in all cases, even if the
+ * entire image has not yet been scaled, dithered, and converted
+ * for the current output device.
+ * If the current output representation is not yet complete, then
+ * <code>drawImage</code> returns <code>false</code>. As more of
+ * the image becomes available, the process that loads the image notifies
+ * the image observer by calling its <code>imageUpdate</code> method.
+ * <p>
+ * A scaled version of an image will not necessarily be
+ * available immediately just because an unscaled version of the
+ * image has been constructed for this output device. Each size of
+ * the image may be cached separately and generated from the original
+ * data in a separate image production sequence.
+ * @param img the specified image to be drawn. This method does
+ * nothing if <code>img</code> is null.
+ * @param x the <i>x</i> coordinate.
+ * @param y the <i>y</i> coordinate.
+ * @param width the width of the rectangle.
+ * @param height the height of the rectangle.
+ * @param observer object to be notified as more of
+ * the image is converted.
+ * @return <code>false</code> if the image pixels are still changing;
+ * <code>true</code> otherwise.
+ * @see java.awt.Image
+ * @see java.awt.image.ImageObserver
+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
+ */
+ public boolean drawImage(Image img, int x, int y,
+ int width, int height,
+ ImageObserver observer) {
+ if (log.check(POILogger.WARN)) {
+ log.log(POILogger.WARN, "Not implemented");
+ }
+ return false;
+ }
+
+ /**
+ * Creates a new <code>Graphics</code> object that is
+ * a copy of this <code>Graphics</code> object.
+ * @return a new graphics context that is a copy of
+ * this graphics context.
+ */
+ public Graphics create() {
+ try {
+ return (Graphics)clone();
+ } catch (CloneNotSupportedException e){
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Gets the font metrics for the specified font.
+ * @return the font metrics for the specified font.
+ * @param f the specified font
+ * @see java.awt.Graphics#getFont
+ * @see java.awt.FontMetrics
+ * @see java.awt.Graphics#getFontMetrics()
+ */
+ @SuppressWarnings("deprecation")
+ @SuppressForbidden
+ public FontMetrics getFontMetrics(Font f) {
+ return Toolkit.getDefaultToolkit().getFontMetrics(f);
+ }
+
+ /**
+ * Sets the paint mode of this graphics context to alternate between
+ * this graphics context's current color and the new specified color.
+ * This specifies that logical pixel operations are performed in the
+ * XOR mode, which alternates pixels between the current color and
+ * a specified XOR color.
+ * <p>
+ * When drawing operations are performed, pixels which are the
+ * current color are changed to the specified color, and vice versa.
+ * <p>
+ * Pixels that are of colors other than those two colors are changed
+ * in an unpredictable but reversible manner; if the same figure is
+ * drawn twice, then all pixels are restored to their original values.
+ * @param c1 the XOR alternation color
+ */
+ public void setXORMode(Color c1) {
+ if (log.check(POILogger.WARN)) {
+ log.log(POILogger.WARN, "Not implemented");
+ }
+ }
+
+ /**
+ * Sets the paint mode of this graphics context to overwrite the
+ * destination with this graphics context's current color.
+ * This sets the logical pixel operation function to the paint or
+ * overwrite mode. All subsequent rendering operations will
+ * overwrite the destination with the current color.
+ */
+ public void setPaintMode() {
+ if (log.check(POILogger.WARN)) {
+ log.log(POILogger.WARN, "Not implemented");
+ }
+ }
+
+ /**
+ * Renders a
+ * {@link RenderableImage},
+ * applying a transform from image space into user space before drawing.
+ * The transformation from user space into device space is done with
+ * the current <code>Transform</code> in the <code>Graphics2D</code>.
+ * The specified transformation is applied to the image before the
+ * transform attribute in the <code>Graphics2D</code> context is applied.
+ * The rendering attributes applied include the <code>Clip</code>,
+ * <code>Transform</code>, and <code>Composite</code> attributes. Note
+ * that no rendering is done if the specified transform is
+ * noninvertible.
+ *<p>
+ * Rendering hints set on the <code>Graphics2D</code> object might
+ * be used in rendering the <code>RenderableImage</code>.
+ * If explicit control is required over specific hints recognized by a
+ * specific <code>RenderableImage</code>, or if knowledge of which hints
+ * are used is required, then a <code>RenderedImage</code> should be
+ * obtained directly from the <code>RenderableImage</code>
+ * and rendered using
+ *{@link #drawRenderedImage(RenderedImage, AffineTransform) drawRenderedImage}.
+ * @param img the image to be rendered. This method does
+ * nothing if <code>img</code> is null.
+ * @param xform the transformation from image space into user space
+ * @see #_transform
+ * @see #setTransform
+ * @see #setComposite
+ * @see #clip
+ * @see #setClip
+ * @see #drawRenderedImage
+ */
+ public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
+ if (log.check(POILogger.WARN)) {
+ log.log(POILogger.WARN, "Not implemented");
+ }
+ }
+
+ /**
+ * Renders a {@link RenderedImage},
+ * applying a transform from image
+ * space into user space before drawing.
+ * The transformation from user space into device space is done with
+ * the current <code>Transform</code> in the <code>Graphics2D</code>.
+ * The specified transformation is applied to the image before the
+ * transform attribute in the <code>Graphics2D</code> context is applied.
+ * The rendering attributes applied include the <code>Clip</code>,
+ * <code>Transform</code>, and <code>Composite</code> attributes. Note
+ * that no rendering is done if the specified transform is
+ * noninvertible.
+ * @param img the image to be rendered. This method does
+ * nothing if <code>img</code> is null.
+ * @param xform the transformation from image space into user space
+ * @see #_transform
+ * @see #setTransform
+ * @see #setComposite
+ * @see #clip
+ * @see #setClip
+ */
+ public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
+ if (log.check(POILogger.WARN)) {
+ log.log(POILogger.WARN, "Not implemented");
+ }
+ }
+
+ protected void applyStroke(SimpleShape<?,?> shape) {
+ if (_stroke instanceof BasicStroke){
+ BasicStroke bs = (BasicStroke)_stroke;
+ shape.setStrokeStyle((double)bs.getLineWidth());
+ float[] dash = bs.getDashArray();
+ if (dash != null) {
+ //TODO: implement more dashing styles
+ shape.setStrokeStyle(StrokeStyle.LineDash.DASH);
+ }
+ }
+ }
+
+ protected void applyPaint(SimpleShape<?,?> shape) {
+ if (_paint instanceof Color) {
+ shape.setFillColor((Color)_paint);
+ }
+ }
+}
diff --git a/src/java/org/apache/poi/sl/usermodel/SimpleShape.java b/src/java/org/apache/poi/sl/usermodel/SimpleShape.java index ceed729e09..8ed151b496 100644 --- a/src/java/org/apache/poi/sl/usermodel/SimpleShape.java +++ b/src/java/org/apache/poi/sl/usermodel/SimpleShape.java @@ -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); } diff --git a/src/java/org/apache/poi/sl/usermodel/SlideShow.java b/src/java/org/apache/poi/sl/usermodel/SlideShow.java index 53449e76d5..968911b95f 100644 --- a/src/java/org/apache/poi/sl/usermodel/SlideShow.java +++ b/src/java/org/apache/poi/sl/usermodel/SlideShow.java @@ -48,6 +48,13 @@ public interface SlideShow< * @return the page size */ Dimension getPageSize(); + + /** + * Change the current page size + * + * @param pgsize page size (in points) + */ + void setPageSize(Dimension pgsize); /** * Returns all Pictures of this slideshow. diff --git a/src/java/org/apache/poi/sl/usermodel/StrokeStyle.java b/src/java/org/apache/poi/sl/usermodel/StrokeStyle.java index 244173fed4..be93a994de 100644 --- a/src/java/org/apache/poi/sl/usermodel/StrokeStyle.java +++ b/src/java/org/apache/poi/sl/usermodel/StrokeStyle.java @@ -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; + } } diff --git a/src/java/org/apache/poi/sl/usermodel/TableCell.java b/src/java/org/apache/poi/sl/usermodel/TableCell.java index 278573bab5..5ad4c4c296 100644 --- a/src/java/org/apache/poi/sl/usermodel/TableCell.java +++ b/src/java/org/apache/poi/sl/usermodel/TableCell.java @@ -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);
}
diff --git a/src/java/org/apache/poi/sl/usermodel/TableShape.java b/src/java/org/apache/poi/sl/usermodel/TableShape.java index 29342e7d94..5614484467 100644 --- a/src/java/org/apache/poi/sl/usermodel/TableShape.java +++ b/src/java/org/apache/poi/sl/usermodel/TableShape.java @@ -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);
}
diff --git a/src/java/org/apache/poi/sl/usermodel/TextBox.java b/src/java/org/apache/poi/sl/usermodel/TextBox.java index 8fa997c89e..bc6951103a 100644 --- a/src/java/org/apache/poi/sl/usermodel/TextBox.java +++ b/src/java/org/apache/poi/sl/usermodel/TextBox.java @@ -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,?> diff --git a/src/java/org/apache/poi/sl/usermodel/TextParagraph.java b/src/java/org/apache/poi/sl/usermodel/TextParagraph.java index 00a016058d..b35d323e1a 100644 --- a/src/java/org/apache/poi/sl/usermodel/TextParagraph.java +++ b/src/java/org/apache/poi/sl/usermodel/TextParagraph.java @@ -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();
}
diff --git a/src/java/org/apache/poi/sl/usermodel/TextRun.java b/src/java/org/apache/poi/sl/usermodel/TextRun.java index bd0164c275..9eb27b616e 100644 --- a/src/java/org/apache/poi/sl/usermodel/TextRun.java +++ b/src/java/org/apache/poi/sl/usermodel/TextRun.java @@ -30,23 +30,23 @@ public interface TextRun { SMALL, ALL } - + String getRawText(); - void setText(String text); - - TextCap getTextCap(); - - /** - * Returns the font color. - * This usually returns a {@link SolidPaint}, but but also other classes are possible - * - * @return the font color/paint - * + void setText(String text); + + TextCap getTextCap(); + + /** + * 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,41 +56,104 @@ 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); + + /** * Returns the font size which is either set directly on this text run or * given from the slide layout - * + * * @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 * font size defaults to the values given from the slide layout - * + * * @param fontSize font size in points, if null the underlying fontsize will be unset */ - void setFontSize(Double fontSize); - String getFontFamily(); - - boolean isBold(); - boolean isItalic(); - boolean isUnderlined(); - boolean isStrikethrough(); - boolean isSubscript(); - boolean isSuperscript(); - - /** - * @return the pitch and family id or -1 if not applicable - */ - byte getPitchAndFamily(); + void setFontSize(Double fontSize); + + /** + * @return font family or null if not set + */ + String getFontFamily(); + + /** + * 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(); } diff --git a/src/java/org/apache/poi/sl/usermodel/TextShape.java b/src/java/org/apache/poi/sl/usermodel/TextShape.java index f487c108a4..0ec2ddfb91 100644 --- a/src/java/org/apache/poi/sl/usermodel/TextShape.java +++ b/src/java/org/apache/poi/sl/usermodel/TextShape.java @@ -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
@@ -89,6 +89,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
@@ -99,6 +139,13 @@ public interface TextShape< * @return text shape margin
*/
Insets2D getInsets();
+
+ /**
+ * Sets the shape margins
+ *
+ * @param insets the new shape margins
+ */
+ void setInsets(Insets2D insets);
/**
* Compute the cumulative height occupied by the text
@@ -113,6 +160,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,
* the whole text block will be displayed centered, i.e. its left and right
@@ -123,12 +178,35 @@ 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();
}
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/Placeholder.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/Placeholder.java deleted file mode 100644 index 087b28c054..0000000000 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/Placeholder.java +++ /dev/null @@ -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
-}
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java index e896420e93..bd150811a2 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java @@ -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())); diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java index b9e4004488..e45df5ee29 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java @@ -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;
@@ -71,14 +76,26 @@ public class XSLFAutoShape extends XSLFTextShape prst.addNewAvLst();
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;
}
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java index 37dbc33a22..dc1ef5af2c 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java @@ -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;
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java index f5d0207b78..daca97131d 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java @@ -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; diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java index 821cb07dff..28c98889cb 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java @@ -88,25 +88,23 @@ 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);
}
-
+
protected CTTransform2D getSafeXfrm() {
CTTransform2D xfrm = getXfrm();
return (xfrm == null ? getSpPr().addNewXfrm() : xfrm);
}
-
+
protected CTTransform2D getXfrm() {
PropertyFetcher<CTTransform2D> fetcher = new PropertyFetcher<CTTransform2D>() {
public boolean fetch(XSLFShape shape) {
@@ -151,7 +149,7 @@ public abstract class XSLFSimpleShape extends XSLFShape ext.setCx(cx);
ext.setCy(cy);
}
-
+
@Override
public void setRotation(double theta) {
getSafeXfrm().setRot((int) (theta * 60000));
@@ -185,7 +183,7 @@ public abstract class XSLFSimpleShape extends XSLFShape return (xfrm == null || !xfrm.isSetFlipV()) ? false : getXfrm().getFlipV();
}
-
+
/**
* Get default line properties defined in the theme (if any).
* Used internally to resolve shape properties.
@@ -199,7 +197,7 @@ public abstract class XSLFSimpleShape extends XSLFShape if (lnRef == null) return null;
// 1-based index of a line style within the style matrix
int idx = (int)lnRef.getIdx();
-
+
XSLFTheme theme = getSheet().getTheme();
if (theme == null) return null;
CTBaseStyles styles = theme.getXmlObject().getThemeElements();
@@ -208,7 +206,7 @@ public abstract class XSLFSimpleShape extends XSLFShape if (styleMatrix == null) return null;
CTLineStyleList lineStyles = styleMatrix.getLnStyleLst();
if (lineStyles == null || lineStyles.sizeOfLnArray() < idx) return null;
-
+
return lineStyles.getLnArray(idx - 1);
}
@@ -262,7 +260,7 @@ public abstract class XSLFSimpleShape extends XSLFShape setValue(null); // use it as 'nofill' value
return true;
}
-
+
PaintStyle paint = null;
PackagePart pp = getSheet().getPackagePart();
for (XmlObject obj : spPr.selectPath("*")) {
@@ -290,11 +288,11 @@ public abstract class XSLFSimpleShape extends XSLFShape PaintStyle paint = fetcher.getValue();
if (paint != null) return paint;
-
+
// line color was not found, check if it is defined in the theme
CTShapeStyle style = getSpStyle();
if (style == null) return null;
-
+
// get a reference to a line style within the style matrix.
CTStyleMatrixReference lnRef = style.getLnRef();
int idx = (int)lnRef.getIdx();
@@ -308,7 +306,7 @@ public abstract class XSLFSimpleShape extends XSLFShape return paint;
}
-
+
/**
*
* @param width line width in points. <code>0</code> means no line
@@ -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
*/
@@ -392,7 +424,7 @@ public abstract class XSLFSimpleShape extends XSLFShape }
}
}
-
+
if (cmpd == null) return null;
switch (cmpd) {
@@ -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) {
@@ -615,7 +635,7 @@ public abstract class XSLFSimpleShape extends XSLFShape }
return geom;
}
-
+
@Override
void copy(XSLFShape sh){
super.copy(sh);
@@ -635,7 +655,7 @@ public abstract class XSLFSimpleShape extends XSLFShape String relId = getSheet().importBlip(blipId, s.getSheet().getPackagePart());
blip.setEmbed(relId);
}
-
+
Color srcLineColor = s.getLineColor();
Color tgtLineColor = getLineColor();
if(srcLineColor != null && !srcLineColor.equals(tgtLineColor)) {
@@ -871,7 +891,31 @@ public abstract class XSLFSimpleShape extends XSLFShape public LineCompound getLineCompound() {
return XSLFSimpleShape.this.getLineCompound();
}
-
+
};
}
+
+ @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);
+ }
+ }
+ }
}
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java index cba6f3e614..1d0d854bda 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java @@ -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; diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java index c728197083..329ebf8994 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java @@ -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; diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java index e6f37386b0..302e064b6a 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java @@ -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; diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java index 7469e25d42..b30b3ba269 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java @@ -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();
}
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableCell.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableCell.java index 29f373929e..b5dcc8e0f5 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableCell.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableCell.java @@ -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;
}
@@ -83,7 +87,7 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape, }
return _tcPr;
}
-
+
@Override
public void setLeftInset(double margin){
CTTableCellProperties pr = getCellProperties(true);
@@ -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;
}
}
+
+ @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;
+ }
+ };
+ }
- private void setBorderWidth(char bltr, double width) {
- CTLineProperties ln = getCTLine(bltr, true);
- ln.setW(Units.toEMU(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);
}
- private double getBorderWidth(char bltr) {
- CTLineProperties ln = getCTLine(bltr, false);
- return (ln == null || !ln.isSetW()) ? defaultBorderWidth : Units.toPoints(ln.getW());
+ public Double getBorderWidth(BorderEdge edge) {
+ CTLineProperties ln = getCTLine(edge, false);
+ return (ln == null || !ln.isSetW()) ? null : Units.toPoints(ln.getW());
}
- private void setBorderColor(char bltr, Color color) {
- CTLineProperties ln = getCTLine(bltr, true);
+ @Override
+ public void setBorderWidth(BorderEdge edge, double width) {
+ CTLineProperties ln = getCTLine(edge, true);
+ ln.setW(Units.toEMU(width));
+ }
- if(color == null){
- ln.addNewNoFill();
- if(ln.isSetSolidFill()) ln.unsetSolidFill();
- } else {
- if(ln.isSetNoFill()) ln.unsetNoFill();
+ private CTLineProperties setBorderDefaults(BorderEdge edge) {
+ CTLineProperties ln = getCTLine(edge, true);
+ 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;
+ }
+
+ @Override
+ public void setBorderColor(BorderEdge edge, Color color) {
+ if (color == null) {
+ throw new IllegalArgumentException("Colors need to be specified.");
}
- }
-
- private Color getBorderColor(char bltr) {
- CTLineProperties ln = getCTLine(bltr,false);
+
+ 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();
@@ -178,71 +289,65 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape, }
byte[] val = fill.getSrgbClr().getVal();
return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);
- }
-
- public void setBorderLeft(double width) {
- setBorderWidth('l', width);
}
- public double getBorderLeft() {
- return getBorderWidth('l');
- }
-
- public void setBorderLeftColor(Color color) {
- setBorderColor('l', color);
- }
-
- public Color getBorderLeftColor() {
- return getBorderColor('l');
- }
+ public LineCompound getBorderCompound(BorderEdge edge) {
+ CTLineProperties ln = getCTLine(edge, false);
+ if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill() || !ln.isSetCmpd()) {
+ return null;
+ }
- public void setBorderRight(double width) {
- setBorderWidth('r', width);
+ return LineCompound.fromOoxmlId(ln.getCmpd().intValue());
}
- public double getBorderRight() {
- return getBorderWidth('r');
- }
+ @Override
+ public void setBorderCompound(BorderEdge edge, LineCompound compound) {
+ if (compound == null) {
+ throw new IllegalArgumentException("LineCompound need to be specified.");
+ }
- public void setBorderRightColor(Color color) {
- setBorderColor('r', color);
+ CTLineProperties ln = setBorderDefaults(edge);
+ ln.setCmpd(STCompoundLine.Enum.forInt(compound.ooxmlId));
}
- public Color getBorderRightColor() {
- return getBorderColor('r');
- }
+ public LineDash getBorderDash(BorderEdge edge) {
+ CTLineProperties ln = getCTLine(edge, false);
+ if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill() || !ln.isSetPrstDash()) {
+ return null;
+ }
- public void setBorderTop(double width) {
- setBorderWidth('t', width);
+ return LineDash.fromOoxmlId(ln.getPrstDash().getVal().intValue());
}
- public double getBorderTop() {
- return getBorderWidth('t');
- }
+ @Override
+ public void setBorderDash(BorderEdge edge, LineDash dash) {
+ if (dash == null) {
+ throw new IllegalArgumentException("LineDash need to be specified.");
+ }
- public void setBorderTopColor(Color color) {
- setBorderColor('t', color);
+ CTLineProperties ln = setBorderDefaults(edge);
+ ln.getPrstDash().setVal(STPresetLineDashVal.Enum.forInt(dash.ooxmlId));
}
- public Color getBorderTopColor() {
- return getBorderColor('t');
+ 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 void setBorderBottom(double width) {
- setBorderWidth('b', width);
- }
+ public void setBorderCap(BorderEdge edge, LineCap cap) {
+ if (cap == null) {
+ throw new IllegalArgumentException("LineCap need to be specified.");
+ }
- public double getBorderBottom() {
- return getBorderWidth('b');
+ CTLineProperties ln = setBorderDefaults(edge);
+ ln.setCap(STLineCap.Enum.forInt(cap.ooxmlId));
}
- 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.
@@ -299,7 +404,7 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape, void setVMerge(boolean merge_) {
((CTTableCell)getXmlObject()).setVMerge(merge_);
}
-
+
@Override
public void setVerticalAlignment(VerticalAlignment anchor){
CTTableCellProperties cellProps = getCellProperties(true);
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextBox.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextBox.java index 65635c4d3c..bb5bd42ae5 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextBox.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextBox.java @@ -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;
}
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java index 68d7438d4e..cc12a63426 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java @@ -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;
}
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java index fd0f44d75a..8ce7c5241e 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java @@ -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);
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java index 8cc90f979f..8a4a935209 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java @@ -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; } - - /** - * @return whether to wrap words within the bounding rectangle - */ + @Override + public void setInsets(Insets2D insets) { + setTopInset(insets.top); + setLeftInset(insets.left); + setBottomInset(insets.bottom); + setRightInset(insets.right); + } + + @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; + } + } + + }
\ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java index 3350149751..525f55ef7b 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java @@ -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());
diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFNotes.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFNotes.java index 0eb075acaf..02fac93bc8 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFNotes.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFNotes.java @@ -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();
}
}
diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java index db2c9833f7..452f22ebcb 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java @@ -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" })
diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTable.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTable.java index 3b7c5cbcc2..cf535b5650 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTable.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTable.java @@ -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();
}
}
\ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextBox.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextBox.java index 59b0dca95c..cee11e541a 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextBox.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextBox.java @@ -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();
}
}
\ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java index e0c4f9dd96..18632ffbf0 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java @@ -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){
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java b/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java index 834dea5ff0..0022822b82 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java @@ -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); } } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java b/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java deleted file mode 100644 index 1e632b8dcc..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java +++ /dev/null @@ -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; - } -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFAutoShape.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFAutoShape.java index 21c07010ca..329f78f423 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFAutoShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFAutoShape.java @@ -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); } /** diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFGroupShape.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFGroupShape.java index 22317fb62a..bbfe93f97c 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFGroupShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFGroupShape.java @@ -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); - - 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)); + boolean isInitialized = !(clientAnchor.getDx1() == 0 && clientAnchor.getRow1() == 0); + + 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 diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPlaceholder.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPlaceholder.java new file mode 100644 index 0000000000..c0a7aef69e --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPlaceholder.java @@ -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; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java index 85f3a906ea..81679c02df 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java @@ -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); diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShapeFactory.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShapeFactory.java index f2aac4da25..4fe197782e 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShapeFactory.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShapeFactory.java @@ -56,7 +56,7 @@ public final class HSLFShapeFactory { EscherPropertyFactory f = new EscherPropertyFactory(); List<EscherProperty> props = f.createProperties( opt.serialize(), 8, opt.getInstance() ); for (EscherProperty ep : props) { - if (ep.getPropertyNumber() == 0x39F + if (ep.getPropertyNumber() == EscherProperties.GROUPSHAPE__TABLEPROPERTIES && ep instanceof EscherSimpleProperty && ((EscherSimpleProperty)ep).getPropertyValue() == 1) { isTable = true; @@ -65,9 +65,13 @@ public final class HSLFShapeFactory { } } - HSLFGroupShape group = (isTable) - ? new HSLFTable(spContainer, parent) - : new HSLFGroupShape(spContainer, parent); + HSLFGroupShape group; + if (isTable) { + group = new HSLFTable(spContainer, parent); + + } else { + group = new HSLFGroupShape(spContainer, parent); + } return group; } @@ -82,65 +86,73 @@ public final class HSLFShapeFactory { shape = new HSLFTextBox(spContainer, parent); break; case HOST_CONTROL: - case FRAME: { - InteractiveInfo info = getClientDataRecord(spContainer, RecordTypes.InteractiveInfo.typeID); - OEShapeAtom oes = getClientDataRecord(spContainer, RecordTypes.OEShapeAtom.typeID); - if(info != null && info.getInteractiveInfoAtom() != null){ - switch(info.getInteractiveInfoAtom().getAction()){ - case InteractiveInfoAtom.ACTION_OLE: - shape = new OLEShape(spContainer, parent); - break; - case InteractiveInfoAtom.ACTION_MEDIA: - shape = new MovieShape(spContainer, parent); - break; - default: - break; - } - } else if (oes != null){ - shape = new OLEShape(spContainer, parent); - } - - if(shape == null) shape = new HSLFPictureShape(spContainer, parent); + case FRAME: + shape = createFrame(spContainer, parent); break; - } case LINE: shape = new HSLFLine(spContainer, parent); break; - case NOT_PRIMITIVE: { - AbstractEscherOptRecord opt = HSLFShape.getEscherChild(spContainer, EscherOptRecord.RECORD_ID); - EscherProperty prop = HSLFShape.getEscherProperty(opt, EscherProperties.GEOMETRY__VERTICES); - if(prop != null) - shape = new HSLFFreeformShape(spContainer, parent); - else { - logger.log(POILogger.INFO, "Creating AutoShape for a NotPrimitive shape"); - shape = new HSLFAutoShape(spContainer, parent); - } + case NOT_PRIMITIVE: + shape = createNonPrimitive(spContainer, parent); break; - } default: - shape = new HSLFAutoShape(spContainer, parent); + EscherTextboxRecord etr = spContainer.getChildById(EscherTextboxRecord.RECORD_ID); + if (parent instanceof HSLFTable && etr != null) { + shape = new HSLFTableCell(spContainer, (HSLFTable)parent); + } else { + shape = new HSLFAutoShape(spContainer, parent); + } break; } return shape; - } + private static HSLFShape createFrame(EscherContainerRecord spContainer, ShapeContainer<HSLFShape,HSLFTextParagraph> parent) { + InteractiveInfo info = getClientDataRecord(spContainer, RecordTypes.InteractiveInfo.typeID); + if(info != null && info.getInteractiveInfoAtom() != null){ + switch(info.getInteractiveInfoAtom().getAction()){ + case InteractiveInfoAtom.ACTION_OLE: + return new OLEShape(spContainer, parent); + case InteractiveInfoAtom.ACTION_MEDIA: + return new MovieShape(spContainer, parent); + default: + break; + } + } + + OEShapeAtom oes = getClientDataRecord(spContainer, RecordTypes.OEShapeAtom.typeID); + if (oes != null){ + return new OLEShape(spContainer, parent); + } + + return new HSLFPictureShape(spContainer, parent); + } + + private static HSLFShape createNonPrimitive(EscherContainerRecord spContainer, ShapeContainer<HSLFShape,HSLFTextParagraph> parent) { + AbstractEscherOptRecord opt = HSLFShape.getEscherChild(spContainer, EscherOptRecord.RECORD_ID); + EscherProperty prop = HSLFShape.getEscherProperty(opt, EscherProperties.GEOMETRY__VERTICES); + if(prop != null) { + return new HSLFFreeformShape(spContainer, parent); + } + + logger.log(POILogger.INFO, "Creating AutoShape for a NotPrimitive shape"); + return new HSLFAutoShape(spContainer, parent); + } + @SuppressWarnings("unchecked") protected static <T extends Record> T getClientDataRecord(EscherContainerRecord spContainer, int recordType) { - Record oep = null; for (Iterator<EscherRecord> it = spContainer.getChildIterator(); it.hasNext();) { EscherRecord obj = it.next(); if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) { byte[] data = obj.serialize(); - Record[] records = Record.findChildRecords(data, 8, data.length - 8); - for (int j = 0; j < records.length; j++) { - if (records[j].getRecordType() == recordType) { - return (T)records[j]; + for (Record r : Record.findChildRecords(data, 8, data.length - 8)) { + if (r.getRecordType() == recordType) { + return (T)r; } } } } - return (T)oep; + return null; } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSheet.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSheet.java index 139840c548..1a46a5e175 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSheet.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSheet.java @@ -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; } diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java index d75aebf007..74761e49ca 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java @@ -27,6 +27,7 @@ import org.apache.poi.sl.draw.DrawPaint; import org.apache.poi.sl.draw.geom.*; import org.apache.poi.sl.usermodel.*; import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; +import org.apache.poi.sl.usermodel.StrokeStyle.LineCap; import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound; import org.apache.poi.sl.usermodel.StrokeStyle.LineDash; import org.apache.poi.util.LittleEndian; @@ -147,11 +148,32 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H } /** + * 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); } @@ -177,7 +199,7 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.LINESTYLE__LINESTYLE); return (prop == null) ? LineCompound.SINGLE : LineCompound.fromNativeId(prop.getPropertyValue()); } - + /** * Sets the line compound style * @@ -204,7 +226,7 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H } public LineDash getLineDash() { - return HSLFSimpleShape.this.getLineDashing(); + return HSLFSimpleShape.this.getLineDash(); } public LineCompound getLineCompound() { @@ -214,23 +236,17 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H public double getLineWidth() { return HSLFSimpleShape.this.getLineWidth(); } - + }; } - /** - * The color used to fill this shape. - */ - public Color getFillColor(){ + @Override + public Color getFillColor() { return getFill().getForegroundColor(); } - /** - * The color used to fill this shape. - * - * @param color the background color - */ - public void setFillColor(Color color){ + @Override + public void setFillColor(Color color) { getFill().setForegroundColor(color); } @@ -353,10 +369,10 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H if (name == null || !name.matches("adj([1-9]|10)?")) { throw new IllegalArgumentException("Adjust value '"+name+"' not supported."); } - + name = name.replace("adj", ""); if ("".equals(name)) name = "1"; - + short escherProp; switch (Integer.parseInt(name)) { case 1: escherProp = EscherProperties.GEOMETRY__ADJUSTVALUE; break; @@ -371,7 +387,7 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H case 10: escherProp = EscherProperties.GEOMETRY__ADJUST10VALUE; break; default: throw new RuntimeException(); } - + int adjval = getEscherProperty(escherProp, -1); return (adjval == -1) ? null : new Guide(name, "val "+adjval); } @@ -386,7 +402,7 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H logger.log(POILogger.WARN, "No preset shape definition for shapeType: "+name); return null; } - + return geom; } @@ -399,7 +415,7 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H int offY = (prop == null) ? 0 : prop.getPropertyValue(); return Math.toDegrees(Math.atan2(offY, offX)); } - + public double getShadowDistance() { AbstractEscherOptRecord opt = getEscherOptRecord(); EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.SHADOWSTYLE__OFFSETX); @@ -415,13 +431,13 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H public Color getShadowColor(){ Color clr = getColor(EscherProperties.SHADOWSTYLE__COLOR, EscherProperties.SHADOWSTYLE__OPACITY, -1); return clr == null ? Color.black : clr; - } - + } + public Shadow<HSLFShape,HSLFTextParagraph> getShadow() { AbstractEscherOptRecord opt = getEscherOptRecord(); EscherProperty shadowType = opt.lookup(EscherProperties.SHADOWSTYLE__TYPE); if (shadowType == null) return null; - + return new Shadow<HSLFShape,HSLFTextParagraph>(){ public SimpleShape<HSLFShape,HSLFTextParagraph> getShadowParent() { return HSLFSimpleShape.this; @@ -443,7 +459,7 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H public SolidPaint getFillStyle() { return DrawPaint.createSolidPaint(getShadowColor()); } - + }; } @@ -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); + } + } + } +}
\ No newline at end of file diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java index b4dd77144f..8e94421c5d 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java @@ -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"); diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java index 7064a862bf..46a356fec9 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java @@ -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)); diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java index 2f785c433b..6bbd345f45 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java @@ -21,17 +21,16 @@ import java.awt.Rectangle; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; -import java.util.Iterator; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.apache.poi.ddf.AbstractEscherOptRecord; import org.apache.poi.ddf.EscherArrayProperty; import org.apache.poi.ddf.EscherContainerRecord; import org.apache.poi.ddf.EscherOptRecord; import org.apache.poi.ddf.EscherProperties; -import org.apache.poi.ddf.EscherRecord; import org.apache.poi.ddf.EscherSimpleProperty; -import org.apache.poi.ddf.EscherTextboxRecord; import org.apache.poi.hslf.record.RecordTypes; import org.apache.poi.sl.usermodel.ShapeContainer; import org.apache.poi.sl.usermodel.TableShape; @@ -46,11 +45,6 @@ import org.apache.poi.util.Units; public final class HSLFTable extends HSLFGroupShape implements HSLFShapeContainer, TableShape<HSLFShape,HSLFTextParagraph> { - protected static final int BORDER_TOP = 1; - protected static final int BORDER_RIGHT = 2; - protected static final int BORDER_BOTTOM = 3; - protected static final int BORDER_LEFT = 4; - protected static final int BORDERS_ALL = 5; protected static final int BORDERS_OUTSIDE = 6; protected static final int BORDERS_INSIDE = 7; @@ -65,10 +59,10 @@ implements HSLFShapeContainer, 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); } - + /** * Create a new Table of the given number of rows and columns * @@ -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,90 +138,171 @@ 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); + for (HSLFLine bt : new HSLFLine[]{ c.borderTop, c.borderRight, c.borderBottom, c.borderLeft }) { + if (bt != null) { + lineSet.add(bt); + } + } + } + } + + for (HSLFLine l : lineSet) { + addShape(l); + } - HSLFLine bt = c.getBorderTop(); - if(bt != null) addShape(bt); + updateRowHeightsProperty(); + } + + private static class TableCellComparator implements Comparator<HSLFShape> { + public int compare( HSLFShape o1, HSLFShape o2 ) { + Rectangle anchor1 = o1.getAnchor(); + Rectangle anchor2 = o2.getAnchor(); + int delta = anchor1.y - anchor2.y; + if (delta == 0) delta = anchor1.x - anchor2.x; + // descending size + if (delta == 0) delta = (anchor2.width*anchor2.height)-(anchor1.width*anchor1.height); + return delta; + } + } - HSLFLine br = c.getBorderRight(); - if(br != null) addShape(br); + private void cellListToArray() { + List<HSLFTableCell> htc = new ArrayList<HSLFTableCell>(); + for (HSLFShape h : getShapes()) { + if (h instanceof HSLFTableCell) { + htc.add((HSLFTableCell)h); + } + } + + if (htc.isEmpty()) { + throw new IllegalStateException("HSLFTable without HSLFTableCells"); + } - HSLFLine bb = c.getBorderBottom(); - if(bb != null) addShape(bb); + Collections.sort(htc, new TableCellComparator()); - HSLFLine bl = c.getBorderLeft(); - if(bl != null) addShape(bl); + List<HSLFTableCell[]> lst = new ArrayList<HSLFTableCell[]>(); + List<HSLFTableCell> row = new ArrayList<HSLFTableCell>(); + int y0 = htc.get(0).getAnchor().y; + for (HSLFTableCell sh : htc) { + Rectangle anchor = sh.getAnchor(); + boolean isNextRow = (anchor.y > y0); + if (isNextRow) { + y0 = anchor.y; + lst.add(row.toArray(new HSLFTableCell[row.size()])); + row.clear(); } + row.add(sh); } + lst.add(row.toArray(new HSLFTableCell[row.size()])); + cells = lst.toArray(new HSLFTableCell[lst.size()][]); } - protected void initTable(){ - List<HSLFShape> shapeList = getShapes(); - - 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()); + 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)); } } - cells = new HSLFTableCell[lst.size()][maxrowlen]; - for (int i = 0; i < lst.size(); i++) { - row = lst.get(i); - for (int j = 0; j < row.size(); j++) { - HSLFTextShape tx = (HSLFTextShape)row.get(j); - cells[i][j] = new HSLFTableCell(tx.getSpContainer(), getParent()); - cells[i][j].setSheet(tx.getSheet()); + + final int threshold = 5; + + // TODO: this only works for non-rotated tables + for (HSLFTableCell[] tca : cells) { + for (HSLFTableCell tc : tca) { + final Rectangle cellAnchor = tc.getAnchor(); + + /** + * x1/y1 --------+ + * | | + * +---------x2/y2 + */ + final double x1 = cellAnchor.getMinX(); + final double x2 = cellAnchor.getMaxX(); + final double y1 = cellAnchor.getMinY(); + final double y2 = cellAnchor.getMaxY(); + + LineRect lline = null, tline = null, rline = null, bline = null; + int lfit = Integer.MAX_VALUE, tfit = Integer.MAX_VALUE, rfit = Integer.MAX_VALUE, bfit = Integer.MAX_VALUE; + + for (LineRect lr : lines) { + // calculate border fit + int lfitx = lr.leftFit(x1, x2, y1, y2); + if (lfitx < lfit) { + lfit = lfitx; + lline = lr; + } + + int tfitx = lr.topFit(x1, x2, y1, y2); + if (tfitx < tfit) { + tfit = tfitx; + tline = lr; + } + + int rfitx = lr.rightFit(x1, x2, y1, y2); + if (rfitx < rfit) { + rfit = rfitx; + rline = lr; + } + + int bfitx = lr.bottomFit(x1, x2, y1, y2); + if (bfitx < bfit) { + bfit = bfitx; + bline = lr; + } + } + + if (lfit < threshold) { + tc.borderLeft = lline.l; + } + if (tfit < threshold) { + tc.borderTop = tline.l; + } + if (rfit < threshold) { + tc.borderRight = rline.l; + } + if (bfit < threshold) { + tc.borderBottom = bline.l; + } } } } + protected void initTable(){ + cellListToArray(); + fitLinesToCells(); + } + /** * Assign the <code>SlideShow</code> this shape belongs to * @@ -232,151 +310,102 @@ implements HSLFShapeContainer, 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); - - if(col < cells[i].length - 1) for (int j = col+1; j < cells[i].length; j++) { - anchor = cells[i][j].getAnchor(); - anchor.x += dx; - cells[i][j].setAnchor(anchor); + @Override + public void setColumnWidth(int col, final double width){ + if (col < 0 || col >= cells[0].length) { + throw new IllegalArgumentException("Column index '"+col+"' is not within range [0-"+(cells[0].length-1)+"]"); + } + double currentWidth = cells[0][col].getAnchor().getWidth(); + double dx = width - currentWidth; + for (HSLFTableCell cols[] : cells) { + Rectangle anchor = cols[col].getAnchor(); + anchor.width = (int)Math.rint(width); + cols[col].setAnchor(anchor); + + if (col < cols.length - 1) { + for (int j = col+1; j < cols.length; j++) { + anchor = cols[j].getAnchor(); + anchor.x += dx; + cols[j].setAnchor(anchor); + } } } Rectangle tblanchor = getAnchor(); tblanchor.width += dx; - setAnchor(tblanchor); + setExteriorAnchor(tblanchor); } - /** - * Format the table and apply the specified Line to all cell boundaries, - * both outside and inside - * - * @param line the border line - */ - public void setAllBorders(HSLFLine line){ - for (int i = 0; i < cells.length; i++) { - for (int j = 0; j < cells[i].length; j++) { - HSLFTableCell cell = cells[i][j]; - cell.setBorderTop(cloneBorder(line)); - cell.setBorderLeft(cloneBorder(line)); - if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line)); - if(i == cells.length - 1) cell.setBorderBottom(cloneBorder(line)); - } - } - } - - /** - * Format the outside border using the specified Line object - * - * @param line the border line - */ - public void setOutsideBorders(HSLFLine line){ - for (int i = 0; i < cells.length; i++) { - for (int j = 0; j < cells[i].length; j++) { - HSLFTableCell cell = cells[i][j]; - - if(j == 0) cell.setBorderLeft(cloneBorder(line)); - if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line)); - else { - cell.setBorderLeft(null); - cell.setBorderLeft(null); - } - - if(i == 0) cell.setBorderTop(cloneBorder(line)); - else if(i == cells.length - 1) cell.setBorderBottom(cloneBorder(line)); - else { - cell.setBorderTop(null); - cell.setBorderBottom(null); + protected HSLFTableCell getRelativeCell(HSLFTableCell origin, int row, int col) { + int thisRow = 0, thisCol = 0; + boolean found = false; + outer: for (HSLFTableCell[] tca : cells) { + thisCol = 0; + for (HSLFTableCell tc : tca) { + if (tc == origin) { + found = true; + break outer; } + thisCol++; } + thisRow++; } - } - - /** - * Format the inside border using the specified Line object - * - * @param line the border line - */ - public void setInsideBorders(HSLFLine line){ - for (int i = 0; i < cells.length; i++) { - for (int j = 0; j < cells[i].length; j++) { - HSLFTableCell cell = cells[i][j]; - if(j != cells[i].length - 1) - cell.setBorderRight(cloneBorder(line)); - else { - cell.setBorderLeft(null); - cell.setBorderLeft(null); - } - if(i != cells.length - 1) cell.setBorderBottom(cloneBorder(line)); - else { - cell.setBorderTop(null); - cell.setBorderBottom(null); - } - } - } + int otherRow = thisRow + row; + int otherCol = thisCol + col; + return (found + && 0 <= otherRow && otherRow < cells.length + && 0 <= otherCol && otherCol < cells[otherRow].length) + ? cells[otherRow][otherCol] : null; } - private HSLFLine cloneBorder(HSLFLine line){ - HSLFLine border = createBorder(); - border.setLineWidth(line.getLineWidth()); - border.setLineDashing(line.getLineDashing()); - border.setLineColor(line.getLineColor()); - border.setLineCompound(line.getLineCompound()); - return border; + @Override + protected void moveAndScale(Rectangle anchorDest){ + super.moveAndScale(anchorDest); + updateRowHeightsProperty(); } - /** - * Create a border to format this table - * - * @return the created border - */ - public HSLFLine createBorder(){ - HSLFLine line = new HSLFLine(this); - + private void updateRowHeightsProperty() { AbstractEscherOptRecord opt = getEscherOptRecord(); - setEscherProperty(opt, EscherProperties.GEOMETRY__SHAPEPATH, -1); - setEscherProperty(opt, EscherProperties.GEOMETRY__FILLOK, -1); - setEscherProperty(opt, EscherProperties.SHADOWSTYLE__SHADOWOBSURED, 0x20000); - setEscherProperty(opt, EscherProperties.THREED__LIGHTFACE, 0x80000); - - return line; + EscherArrayProperty p = opt.lookup(EscherProperties.GROUPSHAPE__TABLEROWPROPERTIES); + byte[] val = new byte[4]; + for (int rowIdx = 0; rowIdx < cells.length; rowIdx++) { + int rowHeight = Units.pointsToMaster(cells[rowIdx][0].getAnchor().height); + LittleEndian.putInt(val, 0, rowHeight); + p.setElement(rowIdx, val); + } } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTableCell.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTableCell.java index e3737e5e18..80341aa354 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTableCell.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTableCell.java @@ -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 setAnchor(Rectangle anchor){ + super.setAnchor(anchor); + + anchorBorder(BorderEdge.top, borderTop); + anchorBorder(BorderEdge.right, borderRight); + anchorBorder(BorderEdge.bottom, borderBottom); + anchorBorder(BorderEdge.left, borderLeft); } - public void setBorderLeft(HSLFLine line) { - if(line != null) anchorBorder(HSLFTable.BORDER_LEFT, line); - this.borderLeft = line; + @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; + } + }; } - public HSLFLine getBorderRight() { - return borderRight; + @Override + public void setBorderStyle(BorderEdge edge, StrokeStyle style) { + if (style == null) { + throw new IllegalArgumentException("StrokeStyle needs to be specified."); + } + + // setting the line cap is not implemented, as the border lines aren't connected + + LineCompound compound = style.getLineCompound(); + if (compound != null) { + setBorderCompound(edge, compound); + } + + LineDash dash = style.getLineDash(); + if (dash != null) { + setBorderDash(edge, dash); + } + + double width = style.getLineWidth(); + setBorderWidth(edge, width); } - public void setBorderRight(HSLFLine line) { - if(line != null) anchorBorder(HSLFTable.BORDER_RIGHT, line); - this.borderRight = line; + + public Double getBorderWidth(BorderEdge edge) { + HSLFLine l; + switch (edge) { + case bottom: l = borderBottom; break; + case top: l = borderTop; break; + case right: l = borderRight; break; + case left: l = borderLeft; break; + default: throw new IllegalArgumentException(); + } + return (l == null) ? null : l.getLineWidth(); + } + + @Override + public void setBorderWidth(BorderEdge edge, double width) { + HSLFLine l = addLine(edge); + l.setLineWidth(width); } - public HSLFLine getBorderTop() { - return borderTop; + public Color getBorderColor(BorderEdge edge) { + HSLFLine l; + switch (edge) { + case bottom: l = borderBottom; break; + case top: l = borderTop; break; + case right: l = borderRight; break; + case left: l = borderLeft; break; + default: throw new IllegalArgumentException(); + } + return (l == null) ? null : l.getLineColor(); } - public void setBorderTop(HSLFLine line) { - if(line != null) anchorBorder(HSLFTable.BORDER_TOP, line); - this.borderTop = line; + @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 HSLFLine getBorderBottom() { - return borderBottom; + 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 void setBorderBottom(HSLFLine line) { - if(line != null) anchorBorder(HSLFTable.BORDER_BOTTOM, line); - this.borderBottom = line; + public LineCompound getBorderCompound(BorderEdge edge) { + HSLFLine l; + switch (edge) { + case bottom: l = borderBottom; break; + case top: l = borderTop; break; + case right: l = borderRight; break; + case left: l = borderLeft; break; + default: throw new IllegalArgumentException(); + } + return (l == null) ? null : l.getLineCompound(); + } + + @Override + public void setBorderCompound(BorderEdge edge, LineCompound compound) { + if (edge == null || compound == null) { + throw new IllegalArgumentException("BorderEdge and/or LineCompound need to be specified."); + } + + HSLFLine l = addLine(edge); + l.setLineCompound(compound); } - public 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); + 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(); } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java index 39fe74c2a9..76969a4713 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java @@ -69,7 +69,7 @@ import org.apache.poi.util.Units; * This class represents a run of text in a powerpoint document. That
* run could be text on a sheet, or text in a note.
* It is only a very basic class for now
- *
+ *
* @author Nick Burch
*/
@@ -98,18 +98,18 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText private int shapeId;
private StyleTextProp9Atom styleTextProp9Atom;
-
+
private boolean _dirty = false;
/**
* Constructs a Text Run from a Unicode text block.
* Either a {@link TextCharsAtom} or a {@link TextBytesAtom} needs to be provided.
- *
+ *
* @param tha the TextHeaderAtom that defines what's what
* @param tba the TextBytesAtom containing the text or null if {@link TextCharsAtom} is provided
* @param tca the TextCharsAtom containing the text or null if {@link TextBytesAtom} is provided
*/
- /* package */ HSLFTextParagraph(
+ /* package */ HSLFTextParagraph(
TextHeaderAtom tha,
TextBytesAtom tba,
TextCharsAtom tca
@@ -137,10 +137,7 @@ public final class HSLFTextParagraph 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;
}
@@ -193,7 +190,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText /**
* Sets the index of the paragraph in the SLWT container
- *
+ *
* @param index
*/
protected void setIndex(int index) {
@@ -241,7 +238,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText /**
* Returns records that make up the list of text paragraphs
* (there can be misc InteractiveInfo, TxInteractiveInfo and other records)
- *
+ *
* @return text run records
*/
public Record[] getRecords() {
@@ -278,7 +275,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText }
/** Numbered List info */
- public void setStyleTextProp9Atom(final StyleTextProp9Atom styleTextProp9Atom) {
+ public void setStyleTextProp9Atom(final StyleTextProp9Atom styleTextProp9Atom) {
this.styleTextProp9Atom = styleTextProp9Atom;
}
@@ -286,7 +283,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText public StyleTextProp9Atom getStyleTextProp9Atom() {
return this.styleTextProp9Atom;
}
-
+
@Override
public Iterator<HSLFTextRun> iterator() {
return _runs.iterator();
@@ -342,13 +339,13 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText if (!_runs.isEmpty()) {
d = _runs.get(0).getFontSize();
}
-
+
return (d != null) ? d : 12d;
}
/**
* Sets the type of horizontal alignment for the paragraph.
- *
+ *
* @param align - the type of alignment
*/
public void setAlignment(org.apache.poi.sl.usermodel.TextParagraph.TextAlign align) {
@@ -386,7 +383,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText public FontAlign getFontAlign() {
TextProp tp = getPropVal(_paragraphStyle, FontAlignmentProp.NAME, this);
if (tp == null) return null;
-
+
switch (tp.getValue()) {
case FontAlignmentProp.BASELINE: return FontAlign.BASELINE;
case FontAlignmentProp.TOP: return FontAlign.TOP;
@@ -413,8 +410,8 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText assert(startAt != null);
return startAt.intValue();
}
-
-
+
+
@Override
public BulletStyle getBulletStyle() {
if (!isBullet() && getAutoNumberingScheme() == null) return null;
@@ -440,7 +437,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText public void setBulletFontColor(Color color) {
setBulletFontColor(DrawPaint.createSolidPaint(color));
}
-
+
@Override
public void setBulletFontColor(PaintStyle color) {
if (!(color instanceof SolidPaint)) {
@@ -450,7 +447,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText Color col = DrawPaint.applyColorTransform(sp.getSolidColor());
HSLFTextParagraph.this.setBulletColor(col);
}
-
+
@Override
public PaintStyle getBulletFontColor() {
Color col = HSLFTextParagraph.this.getBulletColor();
@@ -617,7 +614,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText // TODO: implement
return null;
}
-
+
private Double getPctOrPoints(String propName) {
TextProp tp = getPropVal(_paragraphStyle, propName, this);
if (tp == null) return null;
@@ -632,7 +629,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText }
setParagraphTextPropVal(propName, ival);
}
-
+
private boolean getFlag(int index) {
BitMaskTextProp tp = (BitMaskTextProp)getPropVal(_paragraphStyle, ParagraphFlagsTextProp.NAME, this);
return (tp == null) ? false : tp.getSubValue(index);
@@ -672,7 +669,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText /**
* Returns the named TextProp, either by fetching it (if it exists) or
* adding it (if it didn't)
- *
+ *
* @param props the TextPropCollection to fetch from / add into
* @param name the name of the TextProp to fetch/add
* @param val the value, null if unset
@@ -682,15 +679,15 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText props.removeByName(name);
return;
}
-
+
// Fetch / Add the TextProp
TextProp tp = props.addWithName(name);
tp.setValue(val);
}
-
+
/**
* Check and add linebreaks to text runs leading other paragraphs
- *
+ *
* @param paragraphs
*/
protected static void fixLineEndings(List<HSLFTextParagraph> paragraphs) {
@@ -710,7 +707,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText /**
* Search for a StyleTextPropAtom is for this text header (list of paragraphs)
- *
+ *
* @param header the header
* @param textLen the length of the rawtext, or -1 if the length is not known
*/
@@ -868,7 +865,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText throw new RuntimeException("failed dummy write", e);
}
}
-
+
for (HSLFTextParagraph p : paragraphs) {
p._dirty = false;
}
@@ -877,7 +874,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText /**
* Adds the supplied text onto the end of the TextParagraphs,
* creating a new RichTextRun for it to sit in.
- *
+ *
* @param text the text string used by this object.
*/
protected static HSLFTextRun appendText(List<HSLFTextParagraph> paragraphs, String text, boolean newParagraph) {
@@ -889,9 +886,13 @@ public final class HSLFTextParagraph 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);
@@ -921,7 +921,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText /**
* Sets (overwrites) the current text.
* Uses the properties of the first paragraph / textrun
- *
+ *
* @param text the text string used by this object.
*/
public static HSLFTextRun setText(List<HSLFTextParagraph> paragraphs, String text) {
@@ -980,7 +980,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText /**
* Converts raw text from the text paragraphs to a formatted string,
* i.e. it converts certain control characters used in the raw txt
- *
+ *
* @param rawText the raw text
* @param runType the run type of the shape, paragraph or headerAtom.
* use -1 if unknown
@@ -1024,7 +1024,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText * Scans through the supplied record array, looking for
* a TextHeaderAtom followed by one of a TextBytesAtom or
* a TextCharsAtom. Builds up TextRuns from these
- *
+ *
* @param wrapper an EscherTextboxWrapper
*/
protected static List<HSLFTextParagraph> findTextParagraphs(EscherTextboxWrapper wrapper, HSLFSheet sheet) {
@@ -1103,7 +1103,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText * Scans through the supplied record array, looking for
* a TextHeaderAtom followed by one of a TextBytesAtom or
* a TextCharsAtom. Builds up TextRuns from these
- *
+ *
* @param records the records to build from
*/
protected static List<List<HSLFTextParagraph>> findTextParagraphs(Record[] records) {
@@ -1272,7 +1272,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText EscherTextboxWrapper wrapper = new EscherTextboxWrapper();
return createEmptyParagraph(wrapper);
}
-
+
protected static List<HSLFTextParagraph> createEmptyParagraph(EscherTextboxWrapper wrapper) {
TextHeaderAtom tha = new TextHeaderAtom();
tha.setParentRecord(wrapper);
@@ -1301,10 +1301,10 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText public EscherTextboxWrapper getTextboxWrapper() {
return (EscherTextboxWrapper) _headerAtom.getParentRecord();
}
-
+
protected static Color getColorFromColorIndexStruct(int rgb, HSLFSheet sheet) {
int cidx = rgb >>> 24;
- Color tmp;
+ Color tmp;
switch (cidx) {
// Background ... Accent 3 color
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
@@ -1333,15 +1333,15 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText setPropVal(_paragraphStyle, propName, val);
setDirty();
}
-
+
/**
* marks this paragraph dirty, so its records will be renewed on save
*/
public void setDirty() {
_dirty = true;
}
-
+
public boolean isDirty() {
return _dirty;
}
-}
+}
\ No newline at end of file diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java index fbb908c1c7..a636d346c3 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java @@ -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() { diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextShape.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextShape.java index 1b5bbb83fd..f24173e204 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextShape.java @@ -17,20 +17,37 @@ package org.apache.poi.hslf.usermodel; -import static org.apache.poi.hslf.record.RecordTypes.*; +import static org.apache.poi.hslf.record.RecordTypes.OEPlaceholderAtom; +import static org.apache.poi.hslf.record.RecordTypes.RoundTripHFPlaceholder12; import java.awt.Rectangle; import java.awt.font.FontRenderContext; import java.awt.geom.Rectangle2D; import java.io.IOException; -import java.util.*; - -import org.apache.poi.ddf.*; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.poi.ddf.AbstractEscherOptRecord; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherProperties; +import org.apache.poi.ddf.EscherSimpleProperty; +import org.apache.poi.ddf.EscherTextboxRecord; import org.apache.poi.hslf.exceptions.HSLFException; -import org.apache.poi.hslf.record.*; +import org.apache.poi.hslf.record.EscherTextboxWrapper; +import org.apache.poi.hslf.record.InteractiveInfo; +import org.apache.poi.hslf.record.InteractiveInfoAtom; +import org.apache.poi.hslf.record.OEPlaceholderAtom; +import org.apache.poi.hslf.record.PPDrawing; +import org.apache.poi.hslf.record.RoundTripHFPlaceholder12; +import org.apache.poi.hslf.record.TextHeaderAtom; +import org.apache.poi.hslf.record.TxInteractiveInfoAtom; import org.apache.poi.sl.draw.DrawFactory; import org.apache.poi.sl.draw.DrawTextShape; -import org.apache.poi.sl.usermodel.*; +import org.apache.poi.sl.usermodel.Insets2D; +import org.apache.poi.sl.usermodel.ShapeContainer; +import org.apache.poi.sl.usermodel.TextShape; +import org.apache.poi.sl.usermodel.VerticalAlignment; import org.apache.poi.util.POILogger; import org.apache.poi.util.Units; @@ -57,14 +74,35 @@ implements TextShape<HSLFShape,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 @@ -353,21 +373,33 @@ implements TextShape<HSLFShape,HSLFTextParagraph> { return false; } } + + @Override + public void setHorizontalCentered(Boolean isCentered) { + setAlignment(isCentered, getVerticalAlignment()); + } - public void setVerticalAlignment(VerticalAlignment vAlign) { - setAlignment(isHorizontalCentered(), vAlign); + @Override + public VerticalAlignment getVerticalAlignment() { + int va = getAlignment(); + switch (va) { + case AnchorTop: + case AnchorTopCentered: + case AnchorTopBaseline: + case AnchorTopCenteredBaseline: return VerticalAlignment.TOP; + case AnchorBottom: + case AnchorBottomCentered: + case AnchorBottomBaseline: + case AnchorBottomCenteredBaseline: return VerticalAlignment.BOTTOM; + default: + case AnchorMiddle: + case AnchorMiddleCentered: return VerticalAlignment.MIDDLE; + } } - /** - * Sets if the paragraphs are horizontal centered - * - * @param isCentered true, if the paragraphs are horizontal centered - * A {@code null} values unsets this property. - * - * @see TextShape#isHorizontalCentered() - */ - public void setHorizontalCentered(Boolean isCentered){ - setAlignment(isCentered, getVerticalAlignment()); + @Override + public void setVerticalAlignment(VerticalAlignment vAlign) { + setAlignment(isHorizontalCentered(), vAlign); } /** @@ -479,12 +511,6 @@ implements TextShape<HSLFShape,HSLFTextParagraph> { setEscherProperty(propId, Units.toEMU(margin)); } - @Override - public boolean getWordWrap(){ - int ww = getWordWrapEx(); - return (ww != WrapNone); - } - /** * Returns the value indicating word wrap. * @@ -498,17 +524,28 @@ implements TextShape<HSLFShape,HSLFTextParagraph> { EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT); return prop == null ? WrapSquare : prop.getPropertyValue(); } - + /** * Specifies how the text should be wrapped * * @param wrap the value indicating how the text should be wrapped. * Must be one of the <code>Wrap*</code> constants defined in this class. */ - public void setWordWrap(int wrap){ + public void setWordWrapEx(int wrap){ setEscherProperty(EscherProperties.TEXT__WRAPTEXT, wrap); } + @Override + public boolean getWordWrap(){ + int ww = getWordWrapEx(); + return (ww != WrapNone); + } + + @Override + public void setWordWrap(boolean wrap) { + setWordWrapEx(wrap ? WrapSquare : WrapNone); + } + /** * @return id for the text. */ @@ -700,6 +737,14 @@ implements TextShape<HSLFShape,HSLFTextParagraph> { } @Override + public void setInsets(Insets2D insets) { + setTopInset(insets.top); + setLeftInset(insets.left); + setBottomInset(insets.bottom); + setRightInset(insets.right); + } + + @Override public double getTextHeight(){ DrawFactory drawFact = DrawFactory.getInstance(null); DrawTextShape dts = drawFact.getDrawable(this); @@ -747,14 +792,7 @@ implements TextShape<HSLFShape,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; + } + } + + }
\ No newline at end of file diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestLine.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestLine.java index b26e10215f..c601ca04b7 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestLine.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestLine.java @@ -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); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java index f7fe4c43f4..3ce7a71b99 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java @@ -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); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTable.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTable.java index 8032d2da3e..9b11555b1a 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTable.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTable.java @@ -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){ diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestTable.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestTable.java index 2270cd420f..d32114a7f8 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestTable.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestTable.java @@ -19,23 +19,50 @@ 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")); assertTrue("No Exceptions while reading file", true); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestTextRun.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestTextRun.java index 1cbf238de6..f7db8f5a80 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestTextRun.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestTextRun.java @@ -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); + } } |