<li><link href="#Pictures">How to work with pictures</link></li>
<li><link href="#SlideTitle">How to set slide title</link></li>
<li><link href="#Fill">How to work with slide/shape background</link></li>
+ <li><link href="#Bullets">How to create bulleted lists</link></li>
</ul>
</section>
<section><title>Features</title>
slide.addShape(shape);
</source>
</section>
+ <anchor id="Bullets"/>
+ <section><title>How to create bulleted lists</title>
+ <source>
+ SlideShow ppt = new SlideShow();
+
+ Slide slide = ppt.createSlide();
+
+ TextBox shape = new TextBox();
+ RichTextRun rt = shape.getTextRun().getRichTextRuns()[0];
+ shape.setText(
+ "January\r" +
+ "February\r" +
+ "March\r" +
+ "April");
+ rt.setFontSize(42);
+ rt.setBullet(true);
+ rt.setBulletOffset(0); //bullet offset
+ rt.setTextOffset(50); //text offset (should be greater than bullet offset)
+ rt.setBulletChar('\u263A'); //bullet character
+ slide.addShape(shape);
+
+ shape.setAnchor(new java.awt.Rectangle(50, 50, 500, 300)); //position of the text box in the slide
+ slide.addShape(shape);
+
+ FileOutputStream out = new FileOutputStream("bullets.ppt");
+ ppt.write(out);
+ out.close();
+ </source>
+ </section>
</section>
</section>
--- /dev/null
+\r
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+package org.apache.poi.hslf.examples;\r
+\r
+import org.apache.poi.hslf.usermodel.SlideShow;\r
+import org.apache.poi.hslf.usermodel.RichTextRun;\r
+import org.apache.poi.hslf.model.Slide;\r
+import org.apache.poi.hslf.model.TextBox;\r
+\r
+import java.io.FileOutputStream;\r
+\r
+/**\r
+ * How to create a single-level bulleted list\r
+ * and change some of the bullet attributes\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class BulletsDemo {\r
+\r
+ public static void main(String[] args) throws Exception {\r
+\r
+ SlideShow ppt = new SlideShow();\r
+\r
+ Slide slide = ppt.createSlide();\r
+\r
+ TextBox shape = new TextBox();\r
+ RichTextRun rt = shape.getTextRun().getRichTextRuns()[0];\r
+ shape.setText(\r
+ "January\r" +\r
+ "February\r" +\r
+ "March\r" +\r
+ "April");\r
+ rt.setFontSize(42);\r
+ rt.setBullet(true);\r
+ rt.setBulletOffset(0); //bullet offset\r
+ rt.setTextOffset(50); //text offset (should be greater than bullet offset)\r
+ rt.setBulletChar('\u263A'); //bullet character\r
+ slide.addShape(shape);\r
+\r
+ shape.setAnchor(new java.awt.Rectangle(50, 50, 500, 300)); //position of the text box in the slide\r
+ slide.addShape(shape);\r
+\r
+ FileOutputStream out = new FileOutputStream("bullets.ppt");\r
+ ppt.write(out);\r
+ out.close();\r
+ }\r
+}\r
public static final int ENABLE_NUMBERING_1_IDX = 11;
public static final int ENABLE_NUMBERING_2_IDX = 12;
+ public static String NAME = "char_flags";
public CharFlagsTextProp() {
- super(2,0xffff, "char_flags", new String[] {
+ super(2,0xffff, NAME, new String[] {
"bold", // 0x0001
"italic", // 0x0002
"underline", // 0x0004
--- /dev/null
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.hslf.model.textproperties;\r
+\r
+/** \r
+ * Definition for the common paragraph text property bitset.\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class ParagraphFlagsTextProp extends BitMaskTextProp {\r
+ public static final int BULLET_IDX = 0;\r
+ public static final int BULLET_HARDFONT_IDX = 1;\r
+ public static final int BULLET_HARDCOLOR_IDX = 2;\r
+ public static final int BULLET_HARDSIZE_IDX = 4;\r
+\r
+ public static String NAME = "paragraph_flags";\r
+\r
+ public ParagraphFlagsTextProp() {\r
+ super(2, 0xF, NAME, new String[] {\r
+ "bullet",\r
+ "bullet.hardfont",\r
+ "bullet.hardcolor",\r
+ "bullet.hardsize"}\r
+ );\r
+ }\r
+}
\ No newline at end of file
package org.apache.poi.hslf.record;
-import org.apache.poi.hslf.model.textproperties.AlignmentTextProp;
-import org.apache.poi.hslf.model.textproperties.BitMaskTextProp;
-import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp;
-import org.apache.poi.hslf.model.textproperties.TextProp;
-import org.apache.poi.hslf.model.textproperties.TextPropCollection;
+import org.apache.poi.hslf.model.textproperties.*;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogger;
/** All the different kinds of paragraph properties we might handle */
public static TextProp[] paragraphTextPropTypes = new TextProp[] {
- new BitMaskTextProp(2, 0xF, "paragraph_flags", new String[] {
- "bullet", "bullet.hardfont",
- "bullet.hardcolor", "bullet.hardsize"}
- ),
+ new ParagraphFlagsTextProp(),
new TextProp(2, 0x80, "bullet.char"),
new TextProp(2, 0x10, "bullet.font"),
new TextProp(4, 0x20, "bullet.color"),
new TextProp(2, 0x40, "bullet.size"),
new AlignmentTextProp(),
- new TextProp(2, 0x400, "bullet.offset"),
- new TextProp(2, 0x200, "para_unknown_2"),
new TextProp(2, 0x100, "text.offset"),
+ new TextProp(2, 0x200, "para_unknown_2"),
+ new TextProp(2, 0x400, "bullet.offset"),
new TextProp(2, 0x1000, "linespacing"),
new TextProp(2, 0x2000, "spacebefore"),
new TextProp(2, 0x4000, "spaceafter"),
import java.io.OutputStream;
import java.io.IOException;
-import org.apache.poi.hslf.model.textproperties.BitMaskTextProp;
-import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp;
-import org.apache.poi.hslf.model.textproperties.TextProp;
-import org.apache.poi.hslf.model.textproperties.TextPropCollection;
+import org.apache.poi.hslf.model.textproperties.*;
/**
* TxMasterStyleAtom atom (4003).
return StyleTextPropAtom.paragraphTextPropTypes;
} else {
return new TextProp[] {
- new BitMaskTextProp(2, 0xF, "paragraph_flags", new String[] {
- "bullet", "bullet.hardfont",
- "bullet.hardcolor", "bullet.hardsize"}
- ),
+ new ParagraphFlagsTextProp(),
new TextProp(2, 0x80, "bullet.char"),
new TextProp(2, 0x10, "bullet.font"),
new TextProp(2, 0x40, "bullet.size"),
package org.apache.poi.hslf.usermodel;
-import org.apache.poi.hslf.model.TextRun;
-import org.apache.poi.hslf.model.Sheet;
-import org.apache.poi.hslf.model.SlideMaster;
-import org.apache.poi.hslf.model.MasterSheet;
-import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp;
-import org.apache.poi.hslf.model.textproperties.TextProp;
-import org.apache.poi.hslf.model.textproperties.TextPropCollection;
-import org.apache.poi.hslf.model.textproperties.BitMaskTextProp;
+import org.apache.poi.hslf.model.*;
+import org.apache.poi.hslf.model.Shape;
+import org.apache.poi.hslf.model.textproperties.*;
import org.apache.poi.hslf.record.ColorSchemeAtom;
+import org.apache.poi.hslf.exceptions.HSLFException;
import java.awt.*;
+
/**
* Represents a run of text, all with the same style
*
* text property won't be set if there's no CharFlagsTextProp.
*/
private boolean isCharFlagsTextPropVal(int index) {
- CharFlagsTextProp cftp = null;
- if (characterStyle != null){
- cftp = (CharFlagsTextProp)characterStyle.findByName("char_flags");
+ return getFlag(true, index);
+ }
+
+ private boolean getFlag(boolean isCharacter, int index) {
+ TextPropCollection props;
+ String propname;
+ if (isCharacter){
+ props = characterStyle;
+ propname = CharFlagsTextProp.NAME;
+ } else {
+ props = paragraphStyle;
+ propname = ParagraphFlagsTextProp.NAME;
+ }
+
+ BitMaskTextProp prop = null;
+ if (props != null){
+ prop = (BitMaskTextProp)props.findByName(propname);
}
- if (cftp == null){
+ if (prop == null){
Sheet sheet = parentRun.getSheet();
int txtype = parentRun.getRunType();
MasterSheet master = sheet.getMasterSheet();
if (master != null)
- cftp = (CharFlagsTextProp)master.getStyleAttribute(txtype, getIndentLevel(), "char_flags", true);
+ prop = (BitMaskTextProp)master.getStyleAttribute(txtype, getIndentLevel(), propname, isCharacter);
}
- return cftp == null ? false : cftp.getSubValue(index);
- }
+ return prop == null ? false : prop.getSubValue(index);
+ }
/**
* Set the value of the given flag in the CharFlagsTextProp, adding
* it if required.
*/
private void setCharFlagsTextPropVal(int index, boolean value) {
+ setFlag(true, index, value);
+ }
+
+ private void setFlag(boolean isCharacter, int index, boolean value) {
+ TextPropCollection props;
+ String propname;
+ if (isCharacter){
+ props = characterStyle;
+ propname = CharFlagsTextProp.NAME;
+ } else {
+ props = paragraphStyle;
+ propname = ParagraphFlagsTextProp.NAME;
+ }
+
// Ensure we have the StyleTextProp atom we're going to need
- if(characterStyle == null) {
+ if(props == null) {
parentRun.ensureStyleAtomPresent();
- // characterStyle will now be defined
+ props = isCharacter ? characterStyle : paragraphStyle;
}
-
- CharFlagsTextProp cftp = (CharFlagsTextProp)
- fetchOrAddTextProp(characterStyle, "char_flags");
- cftp.setSubValue(value,index);
- }
+
+ BitMaskTextProp prop = (BitMaskTextProp) fetchOrAddTextProp(props, propname);
+ prop.setSubValue(value,index);
+ }
/**
* Returns the named TextProp, either by fetching it (if it exists) or adding it
public int getIndentLevel() {
return paragraphStyle == null ? 0 : paragraphStyle.getReservedField();
}
-
+
+ /**
+ * Sets whether this rich text run has bullets
+ */
+ public void setBullet(boolean flag) {
+ setFlag(false, ParagraphFlagsTextProp.BULLET_IDX, flag);
+ }
+
+ /**
+ * Returns whether this rich text run has bullets
+ */
+ public boolean isBullet() {
+ return getFlag(false, ParagraphFlagsTextProp.BULLET_IDX);
+ }
+
+ /**
+ * Sets the bullet character
+ */
+ public void setBulletChar(char c) {
+ setParaTextPropVal("bullet.char", c);
+ }
+
+ /**
+ * Returns the bullet character
+ */
+ public char getBulletChar() {
+ return (char)getParaTextPropVal("bullet.char");
+ }
+
+ /**
+ * Sets the bullet offset
+ */
+ public void setBulletOffset(int offset) {
+ setParaTextPropVal("bullet.offset", offset*Shape.MASTER_DPI/Shape.POINT_DPI);
+ }
+
+ /**
+ * Returns the bullet offset
+ */
+ public int getBulletOffset() {
+ return getParaTextPropVal("bullet.offset")*Shape.POINT_DPI/Shape.MASTER_DPI;
+ }
+
+ /**
+ * Sets the text offset
+ */
+ public void setTextOffset(int offset) {
+ setParaTextPropVal("text.offset", offset*Shape.MASTER_DPI/Shape.POINT_DPI);
+ }
+
+ /**
+ * Returns the text offset
+ */
+ public int getTextOffset() {
+ return getParaTextPropVal("text.offset")*Shape.POINT_DPI/Shape.MASTER_DPI;
+ }
// --------------- Internal HSLF methods, not intended for end-user use! -------
/**
public SlideShow() throws IOException {
this(new HSLFSlideShow());
}
-
+
+ /**
+ * Constructs a Powerpoint document from an input stream.
+ */
+ public SlideShow(InputStream inputStream) throws IOException {
+ this(new HSLFSlideShow(inputStream));
+ }
+
/**
* Find the records that are parent-aware, and tell them
* who their parent is
*/
package org.apache.poi.hslf.usermodel;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.FileInputStream;
-import java.io.File;
+import java.io.*;
+import java.awt.*;
import org.apache.poi.hslf.HSLFSlideShow;
-import org.apache.poi.hslf.model.Slide;
-import org.apache.poi.hslf.model.TextRun;
-import org.apache.poi.hslf.model.SlideMaster;
+import org.apache.poi.hslf.model.*;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.SlideListWithText;
}
}
}
+
+ public void testReadParagraphStyles() throws Exception {
+ FileInputStream is = new FileInputStream(new File(System.getProperty("HSLF.testdata.path"), "bullets.ppt"));
+ SlideShow ppt = new SlideShow(is);
+ is.close();
+ assertTrue("No Exceptions while reading file", true);
+
+ RichTextRun rt;
+ TextRun[] txt;
+ Slide[] slide = ppt.getSlides();
+ assertEquals(2, slide.length);
+
+ txt = slide[0].getTextRuns();
+ assertEquals(2, txt.length);
+
+ assertEquals("Title text", txt[0].getRawText());
+ assertEquals(1, txt[0].getRichTextRuns().length);
+ rt = txt[0].getRichTextRuns()[0];
+ assertFalse(rt.isBullet());
+
+ assertEquals(
+ "This is a text placeholder that \r" +
+ "follows the design pattern\r" +
+ "Defined in the slide master\r" +
+ "and has bullets by default", txt[1].getRawText());
+ assertEquals(1, txt[1].getRichTextRuns().length);
+ rt = txt[1].getRichTextRuns()[0];
+ assertEquals('\u2022', rt.getBulletChar());
+ assertTrue(rt.isBullet());
+
+
+ txt = slide[1].getTextRuns();
+ assertEquals(2, txt.length);
+
+ assertEquals(
+ "I\92m a text box\r" +
+ "With bullets\r" +
+ "That follow the design pattern\r" +
+ "From the slide master", txt[0].getRawText());
+ assertEquals(1, txt[0].getRichTextRuns().length);
+ rt = txt[0].getRichTextRuns()[0];
+ assertTrue(rt.isBullet());
+ assertEquals('\u2022', rt.getBulletChar());
+
+ assertEquals(
+ "I\92m a text box with user-defined\r" +
+ "bullet character", txt[1].getRawText());
+ assertEquals(1, txt[1].getRichTextRuns().length);
+ rt = txt[1].getRichTextRuns()[0];
+ assertTrue(rt.isBullet());
+ assertEquals('\u263A', rt.getBulletChar());
+ }
+
+ public void testSetParagraphStyles() throws Exception {
+ SlideShow ppt = new SlideShow();
+
+ Slide slide = ppt.createSlide();
+
+ TextBox shape = new TextBox();
+ RichTextRun rt = shape.getTextRun().getRichTextRuns()[0];
+ shape.setText(
+ "Hello, World!\r" +
+ "This should be\r" +
+ "Multiline text");
+ rt.setFontSize(42);
+ rt.setBullet(true);
+ rt.setTextOffset(50);
+ rt.setBulletOffset(0);
+ rt.setBulletChar('\u263A');
+ slide.addShape(shape);
+
+ assertEquals(42, rt.getFontSize());
+ assertEquals(true, rt.isBullet());
+ assertEquals(50, rt.getTextOffset());
+ assertEquals(0, rt.getBulletOffset());
+ assertEquals('\u263A', rt.getBulletChar());
+
+ shape.setAnchor(new java.awt.Rectangle(50, 50, 500, 300));
+ slide.addShape(shape);
+
+ //serialize and read again
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ppt.write(out);
+ out.close();
+
+ ppt = new SlideShow(new ByteArrayInputStream(out.toByteArray()));
+ slide = ppt.getSlides()[0];
+ shape = (TextBox)slide.getShapes()[0];
+ rt = shape.getTextRun().getRichTextRuns()[0];
+ assertEquals(42, rt.getFontSize());
+ assertEquals(true, rt.isBullet());
+ assertEquals(50, rt.getTextOffset());
+ assertEquals(0, rt.getBulletOffset());
+ assertEquals('\u263A', rt.getBulletChar());
+ }
}