TextShape
or null
+ */
+ public TextShape getPlaceholderByTextType(int type){
+ Shape[] shape = getShapes();
+ for (int i = 0; i < shape.length; i++) {
+ if(shape[i] instanceof TextShape){
+ TextShape tx = (TextShape)shape[i];
+ TextRun run = tx.getTextRun();
+ if(run != null && run.getRunType() == type){
+ return tx;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Search text placeholer by its type
+ *
+ * @param type type of placeholder to search. See {@link org.apache.poi.hslf.record.OEPlaceholderAtom}
+ * @return TextShape
or null
+ */
+ public TextShape getPlaceholder(int type){
+ Shape[] shape = getShapes();
+ for (int i = 0; i < shape.length; i++) {
+ if(shape[i] instanceof TextShape){
+ TextShape tx = (TextShape)shape[i];
+ int placeholderId = 0;
+ OEPlaceholderAtom oep = tx.getPlaceholderAtom();
+ if(oep != null) {
+ placeholderId = oep.getPlaceholderId();
+ } else {
+ //special case for files saved in Office 2007
+ RoundTripHFPlaceholder12 hldr = (RoundTripHFPlaceholder12)tx.getClientDataRecord(RecordTypes.RoundTripHFPlaceholder12.typeID);
+ if(hldr != null) placeholderId = hldr.getPlaceholderId();
+ }
+ if(placeholderId == type){
+ return tx;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return programmable tag associated with this sheet, e.g. ___PPT12
.
+ *
+ * @return programmable tag associated with this sheet.
+ */
+ public String getProgrammableTag(){
+ String tag = null;
+ RecordContainer progTags = (RecordContainer)
+ getSheetContainer().findFirstOfType(
+ RecordTypes.ProgTags.typeID
+ );
+ if(progTags != null) {
+ RecordContainer progBinaryTag = (RecordContainer)
+ progTags.findFirstOfType(
+ RecordTypes.ProgBinaryTag.typeID
+ );
+ if(progBinaryTag != null) {
+ CString binaryTag = (CString)
+ progBinaryTag.findFirstOfType(
+ RecordTypes.CString.typeID
+ );
+ if(binaryTag != null) tag = binaryTag.getText();
+ }
+ }
+
+ return tag;
+
+ }
+
}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java b/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java
index 48f2fdefc..8acbca5ac 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java
@@ -440,14 +440,36 @@ public class Slide extends Sheet
public HeadersFooters getHeadersFooters(){
HeadersFootersContainer hdd = null;
Record[] ch = getSheetContainer().getChildRecords();
+ boolean ppt2007 = false;
for (int i = 0; i < ch.length; i++) {
if(ch[i] instanceof HeadersFootersContainer){
hdd = (HeadersFootersContainer)ch[i];
- break;
+ } else if (ch[i].getRecordType() == RecordTypes.RoundTripContentMasterId.typeID){
+ ppt2007 = true;
}
}
boolean newRecord = false;
- if(hdd == null) return getSlideShow().getSlideHeadersFooters();
- else return new HeadersFooters(hdd, getSlideShow(), newRecord);
+ if(hdd == null && !ppt2007) {
+ return getSlideShow().getSlideHeadersFooters();
+ }
+ else {
+ if(hdd == null) {
+ hdd = new HeadersFootersContainer(HeadersFootersContainer.SlideHeadersFootersContainer);
+ newRecord = true;
+ }
+ return new HeadersFooters(hdd, this, newRecord, ppt2007);
+ }
+ }
+
+ protected void onAddTextShape(TextShape shape) {
+ TextRun run = shape.getTextRun();
+
+ if(_runs == null) _runs = new TextRun[]{run};
+ else {
+ TextRun[] tmp = new TextRun[_runs.length + 1];
+ System.arraycopy(_runs, 0, tmp, 0, _runs.length);
+ tmp[tmp.length-1] = run;
+ _runs = tmp;
+ }
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/SlideMaster.java b/src/scratchpad/src/org/apache/poi/hslf/model/SlideMaster.java
index b48edfc1a..b30a46e38 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/SlideMaster.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/SlideMaster.java
@@ -129,33 +129,15 @@ public class SlideMaster extends MasterSheet {
}
}
- /**
- * Checks if the shape is a placeholder.
- * (placeholders aren't normal shapes, they are visible only in the Edit Master mode)
- *
- *
- * @return true if the shape is a placeholder
- */
- public static boolean isPlaceholder(Shape shape){
- if(!(shape instanceof TextShape)) return false;
-
- TextShape tx = (TextShape)shape;
- TextRun run = tx.getTextRun();
- if(run == null) return false;
-
- Record[] records = run._records;
- for (int i = 0; i < records.length; i++) {
- int type = (int)records[i].getRecordType();
- if (type == RecordTypes.OEPlaceholderAtom.typeID ||
- type == RecordTypes.SlideNumberMCAtom.typeID ||
- type == RecordTypes.DateTimeMCAtom.typeID ||
- type == RecordTypes.GenericDateMCAtom.typeID ||
- type == RecordTypes.FooterMCAtom.typeID ){
- return true;
-
- }
+ protected void onAddTextShape(TextShape shape) {
+ TextRun run = shape.getTextRun();
+ if(_runs == null) _runs = new TextRun[]{run};
+ else {
+ TextRun[] tmp = new TextRun[_runs.length + 1];
+ System.arraycopy(_runs, 0, tmp, 0, _runs.length);
+ tmp[tmp.length-1] = run;
+ _runs = tmp;
}
- return false;
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java
index 44cb2b241..de78b6265 100755
--- a/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java
@@ -199,6 +199,10 @@ public abstract class TextShape extends SimpleShape {
}
if(getAnchor().equals(new Rectangle()) && !"".equals(getText())) resizeToFitText();
}
+ if(_txtrun != null) {
+ _txtrun.setShapeId(getShapeId());
+ sh.onAddTextShape(this);
+ }
}
protected EscherTextboxWrapper getEscherTextboxWrapper(){
@@ -269,7 +273,7 @@ public abstract class TextShape extends SimpleShape {
int type = getTextRun().getRunType();
MasterSheet master = getSheet().getMasterSheet();
if(master != null){
- TextShape masterShape = master.getPlaceholder(type);
+ TextShape masterShape = master.getPlaceholderByTextType(type);
if(masterShape != null) valign = masterShape.getVerticalAlignment();
} else {
//not found in the master sheet. Use the hardcoded defaults.
diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java
index 62a624af9..9bfae4fcc 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java
@@ -26,7 +26,7 @@ import java.io.OutputStream;
/**
* OEPlaceholderAtom (3011).
* - * Atom that describes the placeholder. + * An atom record that specifies whether a shape is a placeholder shape. *
* * @author Yegor Kozlov @@ -34,61 +34,169 @@ import java.io.OutputStream; public class OEPlaceholderAtom extends RecordAtom{ + /** + * The full size of the master body text placeholder shape. + */ public static final int PLACEHOLDER_FULLSIZE = 0; + + /** + * Half of the size of the master body text placeholder shape. + */ public static final int PLACEHOLDER_HALFSIZE = 1; + + /** + * A quarter of the size of the master body text placeholder shape. + */ public static final int PLACEHOLDER_QUARTSIZE = 2; + /** + * MUST NOT be used for this field. + */ public static final byte None = 0; + /** + * The corresponding shape contains the master title text. + * The corresponding slide MUST be a main master slide. + */ public static final byte MasterTitle = 1; + /** + * The corresponding shape contains the master body text. + * The corresponding slide MUST be a main master slide. + */ public static final byte MasterBody = 2; + /** + * The corresponding shape contains the master center title text. + * The corresponding slide MUST be a title master slide. + */ public static final byte MasterCenteredTitle = 3; - public static final byte MasterNotesSlideImage = 4; + /** + * The corresponding shape contains the master sub-title text. + * The corresponding slide MUST be a title master slide. + */ + public static final byte MasterSubTitle = 4; - public static final byte MasterNotesBodyImage = 5; + /** + * The corresponding shape contains the shared properties for slide image shapes. + * The corresponding slide MUST be a notes master slide. + */ + public static final byte MasterNotesSlideImage = 5; - public static final byte MasterDate = 6; + /** + * The corresponding shape contains the master body text. + * The corresponding slide MUST be a notes master slide. + */ + public static final byte MasterNotesBody = 6; - public static final byte MasterSlideNumber = 7; + /** + * The corresponding shape contains the date text field. + * The corresponding slide MUST be a main master slide, title master slide, notes master slide, or handout master slide. + */ + public static final byte MasterDate = 7; - public static final byte MasterFooter = 8; + /** + * The corresponding shape contains a slide number text field. + * The corresponding slide MUST be a main master slide, title master slide, notes master slide, or handout master slide. + */ + public static final byte MasterSlideNumber = 8; - public static final byte MasterHeader = 9; + /** + * The corresponding shape contains a footer text field. + * The corresponding slide MUST be a main master slide, title master slide, notes master slide, or handout master slide. + */ + public static final byte MasterFooter = 9; - public static final byte MasterSubtitle = 10; + /** + * The corresponding shape contains a header text field. + * The corresponding slide must be a notes master slide or handout master slide. + */ + public static final byte MasterHeader = 10; - public static final byte GenericTextObject = 11; + /** + * The corresponding shape contains a presentation slide image. + * The corresponding slide MUST be a notes slide. + */ + public static final byte NotesSlideImage = 11; - public static final byte Title = 12; + /** + * The corresponding shape contains the notes text. + * The corresponding slide MUST be a notes slide. + */ + public static final byte NotesBody = 12; - public static final byte Body = 13; + /** + * The corresponding shape contains the title text. + * The corresponding slide MUST be a presentation slide. + */ + public static final byte Title = 13; - public static final byte NotesBody = 14; + /** + * The corresponding shape contains the body text. + * The corresponding slide MUST be a presentation slide. + */ + public static final byte Body = 14; + /** + * The corresponding shape contains the title text. + * The corresponding slide MUST be a presentation slide. + */ public static final byte CenteredTitle = 15; + /** + * The corresponding shape contains the sub-title text. + * The corresponding slide MUST be a presentation slide. + */ public static final byte Subtitle = 16; + /** + * The corresponding shape contains the title text with vertical text flow. + * The corresponding slide MUST be a presentation slide. + */ public static final byte VerticalTextTitle = 17; + /** + * The corresponding shape contains the body text with vertical text flow. + * The corresponding slide MUST be a presentation slide. + */ public static final byte VerticalTextBody = 18; - public static final byte NotesSlideImage = 19; + /** + * The corresponding shape contains a generic object. + * The corresponding slide MUST be a presentation slide. + */ + public static final byte Object = 19; - public static final byte Object = 20; + /** + * The corresponding shape contains a chart object. + * The corresponding slide MUST be a presentation slide. + */ + public static final byte Graph = 20; - public static final byte Graph = 21; + /** + * The corresponding shape contains a table object. + * The corresponding slide MUST be a presentation slide. + */ + public static final byte Table = 21; - public static final byte Table = 22; + /** + * The corresponding shape contains a clipart object. + * The corresponding slide MUST be a presentation slide. + */ + public static final byte ClipArt = 22; - public static final byte ClipArt = 23; + /** + * The corresponding shape contains an organization chart object. + * The corresponding slide MUST be a presentation slide. + */ + public static final byte OrganizationChart = 23; - public static final byte OrganizationChart = 24; - - public static final byte MediaClip = 25; + /** + * The corresponding shape contains a media object. + * The corresponding slide MUST be a presentation slide. + */ + public static final byte MediaClip = 24; private byte[] _header; @@ -116,11 +224,13 @@ public class OEPlaceholderAtom extends RecordAtom{ */ protected OEPlaceholderAtom(byte[] source, int start, int len) { _header = new byte[8]; - System.arraycopy(source,start,_header,0,8); + int offset = start; + System.arraycopy(source,start,_header,0,8); + offset += _header.length; - placementId = LittleEndian.getInt(source, start); - placeholderId = LittleEndian.getUnsignedByte(source, start+4); - placeholderSize = LittleEndian.getUnsignedByte(source, start+5); + placementId = LittleEndian.getInt(source, offset); offset += 4; + placeholderId = LittleEndian.getUnsignedByte(source, offset); offset++; + placeholderSize = LittleEndian.getUnsignedByte(source, offset); offset++; } /** @@ -130,6 +240,11 @@ public class OEPlaceholderAtom extends RecordAtom{ /** * Returns the placement Id. + *+ * The placement Id is a number assigned to the placeholder. It goes from -1 to the number of placeholders. + * It SHOULD be unique among all PlacholderAtom records contained in the corresponding slide. + * The value 0xFFFFFFFF specifies that the corresponding shape is not a placeholder shape. + *
* * @return the placement Id. */ @@ -139,6 +254,11 @@ public class OEPlaceholderAtom extends RecordAtom{ /** * Sets the placement Id. + *+ * The placement Id is a number assigned to the placeholder. It goes from -1 to the number of placeholders. + * It SHOULD be unique among all PlacholderAtom records contained in the corresponding slide. + * The value 0xFFFFFFFF specifies that the corresponding shape is not a placeholder shape. + *
* * @param id the placement Id. */ @@ -149,6 +269,11 @@ public class OEPlaceholderAtom extends RecordAtom{ /** * Returns the placeholder Id. * + *+ * placeholder Id specifies the type of the placeholder shape. + * The value MUST be one of the static constants defined in this class + *
+ * * @return the placeholder Id. */ public int getPlaceholderId(){ @@ -158,6 +283,10 @@ public class OEPlaceholderAtom extends RecordAtom{ /** * Sets the placeholder Id. * + *+ * placeholder Id specifies the type of the placeholder shape. + * The value MUST be one of the static constants defined in this class + *
* @param id the placeholder Id. */ public void setPlaceholderId(byte id){ diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java b/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java index d7a664725..9c867d5ab 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java @@ -162,6 +162,17 @@ public class RecordTypes { // Records ~12050 seem to be related to Document Encryption public static final Type DocumentEncryptionAtom = new Type(12052,DocumentEncryptionAtom.class); + public static final Type OriginalMainMasterId = new Type(1052,null); + public static final Type CompositeMasterId = new Type(1052,null); + public static final Type RoundTripContentMasterInfo12 = new Type(1054,null); + public static final Type RoundTripShapeId12 = new Type(1055,null); + public static final Type RoundTripHFPlaceholder12 = new Type(1056,RoundTripHFPlaceholder12.class); + public static final Type RoundTripContentMasterId = new Type(1058,null); + public static final Type RoundTripOArtTextStyles12 = new Type(1059,null); + public static final Type RoundTripShapeCheckSumForCustomLayouts12 = new Type(1062,null); + public static final Type RoundTripNotesMasterTextStyles12 = new Type(1063,null); + public static final Type RoundTripCustomTableStyles12 = new Type(1064,null); + //records greater then 0xF000 belong to with Microsoft Office Drawing format also known as Escher public static final int EscherDggContainer = 0xf000; public static final int EscherDgg = 0xf006; diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/RoundTripHFPlaceholder12.java b/src/scratchpad/src/org/apache/poi/hslf/record/RoundTripHFPlaceholder12.java new file mode 100644 index 000000000..0f49b5bd0 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/record/RoundTripHFPlaceholder12.java @@ -0,0 +1,99 @@ +/* ==================================================================== + 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.record; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Date; + +import org.apache.poi.hslf.util.SystemTimeUtils; +import org.apache.poi.util.LittleEndian; + +/** + * An atom record that specifies that a shape is a header or footer placeholder shape + * + * @since PowerPoint 2007 + * @author Yegor Kozlov + */ + +public class RoundTripHFPlaceholder12 extends RecordAtom +{ + /** + * Record header. + */ + private byte[] _header; + + /** + * Specifies the placeholder shape ID. + * + * MUST be {@link OEPlaceholderAtom#MasterDate}, {@link OEPlaceholderAtom#MasterSlideNumber}, + * {@link OEPlaceholderAtom#MasterFooter}, or {@link OEPlaceholderAtom#MasterHeader} + */ + private byte _placeholderId; + + /** + * Constructs the comment atom record from its source data. + * + * @param source the source data as a byte array. + * @param start the start offset into the byte array. + * @param len the length of the slice in the byte array. + */ + protected RoundTripHFPlaceholder12(byte[] source, int start, int len) { + // Get the header. + _header = new byte[8]; + System.arraycopy(source,start,_header,0,8); + + // Get the record data. + _placeholderId = source[start+8]; + } + + /** + * Gets the comment number (note - each user normally has their own count). + * @return the comment number. + */ + public int getPlaceholderId() { + return _placeholderId; + } + + /** + * Sets the comment number (note - each user normally has their own count). + * @param number the comment number. + */ + public void setPlaceholderId(int number) { + _placeholderId = (byte)number; + } + + /** + * Gets the record type. + * @return the record type. + */ + public long getRecordType() { return RecordTypes.RoundTripHFPlaceholder12.typeID; } + + /** + * Write the contents of the record back, so it can be written + * to disk + * + * @param out the output stream to write to. + * @throws java.io.IOException if an error occurs. + */ + public void writeOut(OutputStream out) throws IOException { + out.write(_header); + out.write(_placeholderId); + } +} \ No newline at end of file diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java index 1b2b9f5ee..a546d0444 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java @@ -37,14 +37,7 @@ import org.apache.poi.ddf.EscherRecord; import org.apache.poi.hslf.HSLFSlideShow; import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException; import org.apache.poi.hslf.exceptions.HSLFException; -import org.apache.poi.hslf.model.HeadersFooters; -import org.apache.poi.hslf.model.Notes; -import org.apache.poi.hslf.model.PPFont; -import org.apache.poi.hslf.model.Picture; -import org.apache.poi.hslf.model.Shape; -import org.apache.poi.hslf.model.Slide; -import org.apache.poi.hslf.model.SlideMaster; -import org.apache.poi.hslf.model.TitleMaster; +import org.apache.poi.hslf.model.*; import org.apache.poi.hslf.record.Document; import org.apache.poi.hslf.record.DocumentAtom; import org.apache.poi.hslf.record.FontCollection; @@ -843,6 +836,10 @@ public final class SlideShow { * @return Header / Footer settings for slides */ public HeadersFooters getSlideHeadersFooters(){ + //detect if this ppt was saved in Office2007 + String tag = getSlidesMasters()[0].getProgrammableTag(); + boolean ppt2007 = "___PPT12".equals(tag); + HeadersFootersContainer hdd = null; Record[] ch = _documentRecord.getChildRecords(); for (int i = 0; i < ch.length; i++) { @@ -857,7 +854,7 @@ public final class SlideShow { hdd = new HeadersFootersContainer(HeadersFootersContainer.SlideHeadersFootersContainer); newRecord = true; } - return new HeadersFooters(hdd, this, newRecord); + return new HeadersFooters(hdd, this, newRecord, ppt2007); } /** @@ -866,6 +863,10 @@ public final class SlideShow { * @return Header / Footer settings for notes */ public HeadersFooters getNotesHeadersFooters(){ + //detect if this ppt was saved in Office2007 + String tag = getSlidesMasters()[0].getProgrammableTag(); + boolean ppt2007 = "___PPT12".equals(tag); + HeadersFootersContainer hdd = null; Record[] ch = _documentRecord.getChildRecords(); for (int i = 0; i < ch.length; i++) { @@ -873,13 +874,18 @@ public final class SlideShow { ((HeadersFootersContainer)ch[i]).getOptions() == HeadersFootersContainer.NotesHeadersFootersContainer){ hdd = (HeadersFootersContainer)ch[i]; break; - } + } } boolean newRecord = false; if(hdd == null) { hdd = new HeadersFootersContainer(HeadersFootersContainer.NotesHeadersFootersContainer); newRecord = true; } - return new HeadersFooters(hdd, this, newRecord); + if(ppt2007 && _notes.length > 0){ + return new HeadersFooters(hdd, _notes[0], newRecord, ppt2007); + } else { + return new HeadersFooters(hdd, this, newRecord, ppt2007); + } } + } diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/data/headers_footers_2007.ppt b/src/scratchpad/testcases/org/apache/poi/hslf/data/headers_footers_2007.ppt new file mode 100644 index 000000000..51b2c53b6 Binary files /dev/null and b/src/scratchpad/testcases/org/apache/poi/hslf/data/headers_footers_2007.ppt differ diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHeadersFooters.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHeadersFooters.java index 8b1cdbe09..39255d3e8 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHeadersFooters.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHeadersFooters.java @@ -77,6 +77,112 @@ public class TestHeadersFooters extends TestCase assertEquals("custom date format", hd2.getDateTimeText()); } + /** + * If Headers / Footers are not set, all the getters should returnfalse
or null
+ */
+ public void testReadNoHeadersFooters() throws Exception
+ {
+ File file = new File(cwd, "basic_test_ppt_file.ppt");
+ FileInputStream is = new FileInputStream(file);
+ SlideShow ppt = new SlideShow(is);
+ is.close();
+
+ HeadersFooters slideHdd = ppt.getSlideHeadersFooters();
+ assertFalse(slideHdd.isFooterVisible());
+ assertNull(slideHdd.getFooterText());
+ assertFalse(slideHdd.isSlideNumberVisible());
+ assertFalse(slideHdd.isHeaderVisible());
+ assertNull(slideHdd.getHeaderText());
+ assertFalse(slideHdd.isUserDateVisible());
+ assertNull(slideHdd.getDateTimeText());
+
+
+ HeadersFooters notesHdd = ppt.getNotesHeadersFooters();
+ assertFalse(notesHdd.isFooterVisible());
+ assertNull(notesHdd.getFooterText());
+ assertFalse(notesHdd.isHeaderVisible());
+ assertNull(notesHdd.getHeaderText());
+ assertFalse(notesHdd.isUserDateVisible());
+ assertNull(notesHdd.getDateTimeText());
+
+ Slide[] slide = ppt.getSlides();
+ for(int i=0 ; i < slide.length; i++){
+ HeadersFooters hd1 = slide[i].getHeadersFooters();
+ assertFalse(hd1.isFooterVisible());
+ assertNull(hd1.getFooterText());
+ assertFalse(hd1.isHeaderVisible());
+ assertNull(hd1.getHeaderText());
+ assertFalse(hd1.isUserDateVisible());
+ assertNull(hd1.getDateTimeText());
+ }
+ }
+
+ /**
+ * Test extraction of headers / footers from PPTs saved in Office 2007
+ */
+ public void testRead2007() throws Exception
+ {
+ File file = new File(cwd, "headers_footers_2007.ppt");
+ FileInputStream is = new FileInputStream(file);
+ SlideShow ppt = new SlideShow(is);
+ is.close();
+
+ HeadersFooters slideHdd = ppt.getSlideHeadersFooters();
+ assertTrue(slideHdd.isFooterVisible());
+ assertEquals("THE FOOTER TEXT", slideHdd.getFooterText());
+ assertTrue(slideHdd.isSlideNumberVisible());
+ assertFalse(slideHdd.isHeaderVisible());
+ assertNull(slideHdd.getHeaderText());
+ assertTrue(slideHdd.isUserDateVisible());
+ assertEquals("Wednesday, August 06, 2008", slideHdd.getDateTimeText());
+
+
+ HeadersFooters notesHdd = ppt.getNotesHeadersFooters();
+ assertTrue(notesHdd.isFooterVisible());
+ assertEquals("THE NOTES FOOTER TEXT", notesHdd.getFooterText());
+ assertTrue(notesHdd.isHeaderVisible());
+ assertEquals("THE NOTES HEADER TEXT", notesHdd.getHeaderText());
+ assertTrue(notesHdd.isUserDateVisible());
+ assertTrue(notesHdd.isDateTimeVisible());
+ //TODO: depending on the formatId getDateTimeText() should return formatted date
+ //assertEquals("08/12/08", notesHdd.getDateTimeText());
+
+ //per-slide headers / footers
+ Slide[] slide = ppt.getSlides();
+ //the first slide uses presentation-scope headers / footers
+ HeadersFooters hd1 = slide[0].getHeadersFooters();
+ assertTrue(hd1.isFooterVisible());
+ assertEquals("THE FOOTER TEXT", hd1.getFooterText());
+ assertTrue(hd1.isSlideNumberVisible());
+ assertFalse(hd1.isHeaderVisible());
+ assertNull(hd1.getHeaderText());
+ assertTrue(hd1.isUserDateVisible());
+ assertTrue(hd1.isDateTimeVisible());
+ assertEquals("Wednesday, August 06, 2008", hd1.getDateTimeText());
+
+ //the second slide uses custom per-slide headers / footers
+ HeadersFooters hd2 = slide[1].getHeadersFooters();
+ assertTrue(hd2.isFooterVisible());
+ assertEquals("THE FOOTER TEXT FOR SLIDE 2", hd2.getFooterText());
+ assertTrue(hd2.isSlideNumberVisible());
+ assertFalse(hd2.isHeaderVisible());
+ assertNull(hd2.getHeaderText());
+ assertTrue(hd2.isUserDateVisible());
+ assertTrue(hd2.isDateTimeVisible());
+ assertEquals("August 06, 2008", hd2.getDateTimeText());
+
+ //the third slide uses per-slide headers / footers
+ HeadersFooters hd3 = slide[2].getHeadersFooters();
+ assertTrue(hd3.isFooterVisible());
+ assertEquals("THE FOOTER TEXT", hd3.getFooterText());
+ assertTrue(hd3.isSlideNumberVisible());
+ assertFalse(hd3.isHeaderVisible());
+ assertNull(hd3.getHeaderText());
+ assertTrue(hd3.isUserDateVisible());
+ assertTrue(hd3.isDateTimeVisible());
+ assertEquals("Wednesday, August 06, 2008", hd3.getDateTimeText());
+ }
+
public void testCreateSlideFooters() throws Exception
{
SlideShow ppt = new SlideShow();
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextRun.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextRun.java
index 7b75c3676..6463da4c3 100644
--- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextRun.java
+++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextRun.java
@@ -445,4 +445,55 @@ public class TestTextRun extends TestCase {
assertEquals("Sdfsdfs\n" +
"Sdfsdf\n", rt[1].getText());
}
+
+ /**
+ * Test creation of TextRun objects.
+ */
+ public void testAddTextRun() throws Exception{
+ SlideShow ppt = new SlideShow();
+ Slide slide = ppt.createSlide();
+
+ assertNull(slide.getTextRuns());
+
+ TextBox shape1 = new TextBox();
+ TextRun run1 = shape1.getTextRun();
+ assertSame(run1, shape1.createTextRun());
+ run1.setText("Text 1");
+ slide.addShape(shape1);
+
+ //The array of Slide's text runs must be updated when new text shapes are added.
+ TextRun[] runs = slide.getTextRuns();
+ assertNotNull(runs);
+ assertSame(run1, runs[0]);
+
+ TextBox shape2 = new TextBox();
+ TextRun run2 = shape2.getTextRun();
+ assertSame(run2, shape2.createTextRun());
+ run2.setText("Text 2");
+ slide.addShape(shape2);
+
+ runs = slide.getTextRuns();
+ assertEquals(2, runs.length);
+
+ assertSame(run1, runs[0]);
+ assertSame(run2, runs[1]);
+
+ //as getShapes()
+ Shape[] sh = slide.getShapes();
+ assertEquals(2, sh.length);
+ assertTrue(sh[0] instanceof TextBox);
+ TextBox box1 = (TextBox)sh[0];
+ assertSame(run1, box1.getTextRun());
+ TextBox box2 = (TextBox)sh[1];
+ assertSame(run2, box2.getTextRun());
+
+ //test Table - a complex group of shapes containing text objects
+ Slide slide2 = ppt.createSlide();
+ assertNull(slide2.getTextRuns());
+ Table table = new Table(2, 2);
+ slide2.addShape(table);
+ runs = slide2.getTextRuns();
+ assertNotNull(runs);
+ assertEquals(4, runs.length);
+ }
}