mirror of https://github.com/apache/poi.git
support for text bullets
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@542179 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
bd4852d48b
commit
ff60d78860
|
@ -37,6 +37,7 @@
|
|||
<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>
|
||||
|
@ -319,6 +320,35 @@
|
|||
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>
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
|
||||
/* ====================================================================
|
||||
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.examples;
|
||||
|
||||
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||
import org.apache.poi.hslf.usermodel.RichTextRun;
|
||||
import org.apache.poi.hslf.model.Slide;
|
||||
import org.apache.poi.hslf.model.TextBox;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
/**
|
||||
* How to create a single-level bulleted list
|
||||
* and change some of the bullet attributes
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class BulletsDemo {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -32,8 +32,9 @@ public class CharFlagsTextProp extends BitMaskTextProp {
|
|||
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
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/* ====================================================================
|
||||
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.textproperties;
|
||||
|
||||
/**
|
||||
* Definition for the common paragraph text property bitset.
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class ParagraphFlagsTextProp extends BitMaskTextProp {
|
||||
public static final int BULLET_IDX = 0;
|
||||
public static final int BULLET_HARDFONT_IDX = 1;
|
||||
public static final int BULLET_HARDCOLOR_IDX = 2;
|
||||
public static final int BULLET_HARDSIZE_IDX = 4;
|
||||
|
||||
public static String NAME = "paragraph_flags";
|
||||
|
||||
public ParagraphFlagsTextProp() {
|
||||
super(2, 0xF, NAME, new String[] {
|
||||
"bullet",
|
||||
"bullet.hardfont",
|
||||
"bullet.hardcolor",
|
||||
"bullet.hardsize"}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -19,11 +19,7 @@
|
|||
|
||||
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;
|
||||
|
||||
|
@ -95,18 +91,15 @@ public class StyleTextPropAtom extends RecordAtom
|
|||
|
||||
/** 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"),
|
||||
|
|
|
@ -23,10 +23,7 @@ import org.apache.poi.util.LittleEndian;
|
|||
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).
|
||||
|
@ -177,10 +174,7 @@ public class TxMasterStyleAtom extends RecordAtom {
|
|||
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"),
|
||||
|
|
|
@ -20,18 +20,15 @@
|
|||
|
||||
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
|
||||
*
|
||||
|
@ -164,37 +161,64 @@ public class RichTextRun
|
|||
* 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;
|
||||
}
|
||||
if (cftp == null){
|
||||
|
||||
BitMaskTextProp prop = null;
|
||||
if (props != null){
|
||||
prop = (BitMaskTextProp)props.findByName(propname);
|
||||
}
|
||||
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) {
|
||||
// Ensure we have the StyleTextProp atom we're going to need
|
||||
if(characterStyle == null) {
|
||||
parentRun.ensureStyleAtomPresent();
|
||||
// characterStyle will now be defined
|
||||
}
|
||||
|
||||
CharFlagsTextProp cftp = (CharFlagsTextProp)
|
||||
fetchOrAddTextProp(characterStyle, "char_flags");
|
||||
cftp.setSubValue(value,index);
|
||||
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(props == null) {
|
||||
parentRun.ensureStyleAtomPresent();
|
||||
props = isCharacter ? characterStyle : paragraphStyle;
|
||||
}
|
||||
|
||||
BitMaskTextProp prop = (BitMaskTextProp) fetchOrAddTextProp(props, propname);
|
||||
prop.setSubValue(value,index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the named TextProp, either by fetching it (if it exists) or adding it
|
||||
* (if it didn't)
|
||||
|
@ -396,7 +420,62 @@ public class RichTextRun
|
|||
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! -------
|
||||
|
||||
/**
|
||||
|
|
|
@ -119,7 +119,14 @@ public class SlideShow
|
|||
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
|
||||
|
|
Binary file not shown.
|
@ -16,15 +16,11 @@
|
|||
*/
|
||||
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;
|
||||
|
||||
|
@ -458,4 +454,99 @@ if(false) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
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’m 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’m 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());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue