Bug 55164 - Support for adding slide notes
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1635010 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
5dcf6b1a29
commit
1d84cd9828
@ -112,7 +112,16 @@ public abstract class POIXMLRelation {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return type of the obejct used to construct instances of this relationship
|
||||
* Returns the index of the filename within the package for the given part.
|
||||
* e.g. 4 for /xl/comments4.xml
|
||||
*/
|
||||
public Integer getFileNameIndex(POIXMLDocumentPart part) {
|
||||
String regex = _defaultName.replace("#", "(\\d+)");
|
||||
return Integer.parseInt(part.getPackageRelationship().getTargetURI().getPath().replaceAll(regex, "$1"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return type of the object used to construct instances of this relationship
|
||||
*
|
||||
* @return the class of the object used to construct instances of this relation
|
||||
*/
|
||||
|
@ -49,6 +49,8 @@ import org.apache.xmlbeans.XmlObject;
|
||||
import org.apache.xmlbeans.XmlOptions;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
|
||||
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTNotesMasterIdList;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTNotesMasterIdListEntry;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTPresentation;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideIdList;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideIdListEntry;
|
||||
@ -155,7 +157,6 @@ public class XMLSlideShow extends POIXMLDocument {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void commit() throws IOException {
|
||||
XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
|
||||
@ -245,6 +246,95 @@ public class XMLSlideShow extends POIXMLDocument {
|
||||
return createSlide(layout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return notes slide for the specified slide or create new if it does not exist yet.
|
||||
*/
|
||||
public XSLFNotes getNotesSlide(XSLFSlide slide) {
|
||||
|
||||
XSLFNotes notesSlide = slide.getNotes();
|
||||
if (notesSlide == null) {
|
||||
notesSlide = createNotesSlide(slide);
|
||||
}
|
||||
|
||||
return notesSlide;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a blank notes slide.
|
||||
*/
|
||||
private XSLFNotes createNotesSlide(XSLFSlide slide) {
|
||||
|
||||
if (_notesMaster == null) {
|
||||
createNotesMaster();
|
||||
}
|
||||
|
||||
Integer slideIndex = XSLFRelation.SLIDE.getFileNameIndex(slide);
|
||||
|
||||
XSLFNotes notesSlide = (XSLFNotes) createRelationship(XSLFRelation.NOTES, XSLFFactory.getInstance(), slideIndex);
|
||||
|
||||
notesSlide.addRelation(_notesMaster.getPackageRelationship().getId(), _notesMaster);
|
||||
PackagePartName notesMasterPackagePartName = _notesMaster.getPackagePart().getPartName();
|
||||
notesSlide.getPackagePart().addRelationship(notesMasterPackagePartName, TargetMode.INTERNAL,
|
||||
_notesMaster.getPackageRelationship().getRelationshipType());
|
||||
|
||||
slide.addRelation(notesSlide.getPackageRelationship().getId(), notesSlide);
|
||||
PackagePartName notesSlidesPackagePartName = notesSlide.getPackagePart().getPartName();
|
||||
slide.getPackagePart().addRelationship(notesSlidesPackagePartName, TargetMode.INTERNAL,
|
||||
notesSlide.getPackageRelationship().getRelationshipType());
|
||||
|
||||
notesSlide.addRelation(slide.getPackageRelationship().getId(), slide);
|
||||
PackagePartName slidesPackagePartName = slide.getPackagePart().getPartName();
|
||||
notesSlide.getPackagePart().addRelationship(slidesPackagePartName, TargetMode.INTERNAL,
|
||||
slide.getPackageRelationship().getRelationshipType());
|
||||
|
||||
notesSlide.importContent(_notesMaster);
|
||||
|
||||
return notesSlide;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a notes master.
|
||||
*/
|
||||
public void createNotesMaster() {
|
||||
|
||||
_notesMaster = (XSLFNotesMaster) createRelationship(XSLFRelation.NOTES_MASTER,
|
||||
XSLFFactory.getInstance(), 1);
|
||||
|
||||
CTNotesMasterIdList notesMasterIdList = _presentation.addNewNotesMasterIdLst();
|
||||
CTNotesMasterIdListEntry notesMasterId = notesMasterIdList.addNewNotesMasterId();
|
||||
notesMasterId.setId(_notesMaster.getPackageRelationship().getId());
|
||||
|
||||
Integer themeIndex = 1;
|
||||
List<Integer> themeIndexList = new ArrayList<Integer>();
|
||||
for (POIXMLDocumentPart p : getRelations()) {
|
||||
if (p instanceof XSLFTheme) {
|
||||
themeIndexList.add(XSLFRelation.THEME.getFileNameIndex(p));
|
||||
}
|
||||
}
|
||||
|
||||
if (!themeIndexList.isEmpty()) {
|
||||
Boolean found = false;
|
||||
for (Integer i = 1; i <= themeIndexList.size(); i++) {
|
||||
if (!themeIndexList.contains(i)) {
|
||||
found = true;
|
||||
themeIndex = i;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
themeIndex = themeIndexList.size() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
XSLFTheme theme = (XSLFTheme) createRelationship(XSLFRelation.THEME,
|
||||
XSLFFactory.getInstance(), themeIndex);
|
||||
theme.importTheme(getSlides()[0].getTheme());
|
||||
|
||||
_notesMaster.addRelation(theme.getPackageRelationship().getId(), theme);
|
||||
PackagePartName themePackagePartName = theme.getPackagePart().getPartName();
|
||||
_notesMaster.getPackagePart().addRelationship(themePackagePartName, TargetMode.INTERNAL,
|
||||
theme.getPackageRelationship().getRelationshipType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Notes Master, if there is one.
|
||||
* (May not be present if no notes exist)
|
||||
|
@ -16,6 +16,8 @@
|
||||
==================================================================== */
|
||||
package org.apache.poi.xslf.usermodel;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.POIXMLDocumentPart;
|
||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||
@ -25,8 +27,6 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTCommonSlideData;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTNotesSlide;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.NotesDocument;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Beta
|
||||
public final class XSLFNotes extends XSLFSheet {
|
||||
private CTNotesSlide _notes;
|
||||
@ -57,12 +57,10 @@ public final class XSLFNotes extends XSLFSheet {
|
||||
setCommonSlideData(_notes.getCSld());
|
||||
}
|
||||
|
||||
|
||||
private static CTNotesSlide prototype(){
|
||||
CTNotesSlide ctNotes = CTNotesSlide.Factory.newInstance();
|
||||
CTCommonSlideData cSld = ctNotes.addNewCSld();
|
||||
|
||||
// TODO What else is needed for a mininum notes?
|
||||
cSld.addNewSpTree();
|
||||
|
||||
return ctNotes;
|
||||
}
|
||||
@ -77,6 +75,11 @@ public final class XSLFNotes extends XSLFSheet {
|
||||
return "notes";
|
||||
}
|
||||
|
||||
@Override
|
||||
public XSLFTheme getTheme(){
|
||||
return getMasterSheet().getTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public XSLFNotesMaster getMasterSheet() {
|
||||
for (POIXMLDocumentPart p : getRelations()) {
|
||||
|
@ -16,15 +16,19 @@
|
||||
==================================================================== */
|
||||
package org.apache.poi.xslf.usermodel;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.poi.POIXMLDocumentPart;
|
||||
import org.apache.poi.POIXMLException;
|
||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||
import org.apache.poi.util.Beta;
|
||||
import org.apache.xmlbeans.XmlException;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTColorMapping;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTNotesMaster;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.NotesMasterDocument;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Notes master object associated with this layout.
|
||||
* <p>
|
||||
@ -44,10 +48,11 @@ import java.io.IOException;
|
||||
@Beta
|
||||
public class XSLFNotesMaster extends XSLFSheet {
|
||||
private CTNotesMaster _slide;
|
||||
private XSLFTheme _theme;
|
||||
|
||||
XSLFNotesMaster() {
|
||||
super();
|
||||
_slide = CTNotesMaster.Factory.newInstance();
|
||||
_slide = prototype();
|
||||
}
|
||||
|
||||
protected XSLFNotesMaster(PackagePart part, PackageRelationship rel) throws IOException, XmlException {
|
||||
@ -58,6 +63,21 @@ import java.io.IOException;
|
||||
setCommonSlideData(_slide.getCSld());
|
||||
}
|
||||
|
||||
private static CTNotesMaster prototype() {
|
||||
InputStream is = XSLFNotesMaster.class.getResourceAsStream("notesMaster.xml");
|
||||
if (is == null) {
|
||||
throw new POIXMLException("Missing resource 'notesMaster.xml'");
|
||||
}
|
||||
|
||||
try {
|
||||
NotesMasterDocument doc = NotesMasterDocument.Factory.parse(is);
|
||||
CTNotesMaster slide = doc.getNotesMaster();
|
||||
return slide;
|
||||
} catch (Exception e) {
|
||||
throw new POIXMLException("Can't initialize NotesMaster", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CTNotesMaster getXmlObject() {
|
||||
return _slide;
|
||||
@ -73,4 +93,20 @@ import java.io.IOException;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XSLFTheme getTheme() {
|
||||
if (_theme == null) {
|
||||
for (POIXMLDocumentPart p : getRelations()) {
|
||||
if (p instanceof XSLFTheme) {
|
||||
_theme = (XSLFTheme) p;
|
||||
CTColorMapping cmap = _slide.getClrMap();
|
||||
if (cmap != null) {
|
||||
_theme.initColorMap(cmap);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return _theme;
|
||||
}
|
||||
}
|
@ -999,13 +999,22 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
||||
"declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " +
|
||||
"declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " +
|
||||
".//p:txStyles/p:" + defaultStyleSelector +"/a:lvl" +(level+1)+ "pPr");
|
||||
if (o.length == 1){
|
||||
return (CTTextParagraphProperties)o[0];
|
||||
} else {
|
||||
o = masterSheet.getXmlObject().selectPath(
|
||||
"declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " +
|
||||
"declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " +
|
||||
".//p:notesStyle/a:lvl" +(level+1)+ "pPr");
|
||||
|
||||
if (o.length == 1){
|
||||
return (CTTextParagraphProperties)o[0];
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Failed to fetch default style for " +
|
||||
defaultStyleSelector + " and level=" + level);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean fetchParagraphProperty(ParagraphPropertyFetcher visitor){
|
||||
boolean ok = false;
|
||||
|
@ -16,6 +16,13 @@
|
||||
==================================================================== */
|
||||
package org.apache.poi.xslf.usermodel;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import org.apache.poi.POIXMLDocumentPart;
|
||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||
@ -32,12 +39,6 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeStyleSheet;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.ThemeDocument;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A shared style sheet in a .pptx slide show
|
||||
*
|
||||
@ -61,6 +62,11 @@ public class XSLFTheme extends POIXMLDocumentPart {
|
||||
initialize();
|
||||
}
|
||||
|
||||
public void importTheme(XSLFTheme theme) {
|
||||
_theme = theme.getXmlObject();
|
||||
_schemeColors = theme._schemeColors;
|
||||
}
|
||||
|
||||
private void initialize(){
|
||||
CTBaseStyles elems = _theme.getThemeElements();
|
||||
CTColorScheme scheme = elems.getClrScheme();
|
||||
|
@ -0,0 +1,97 @@
|
||||
/* ====================================================================
|
||||
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;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import org.apache.poi.xslf.XSLFTestDataSamples;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TestXSLFNotes {
|
||||
|
||||
@Test
|
||||
public void createNewNote() {
|
||||
|
||||
XMLSlideShow ppt = new XMLSlideShow();
|
||||
XSLFSlide slide1 = ppt.createSlide();
|
||||
|
||||
assertNull(ppt.getNotesMaster());
|
||||
assertNull(slide1.getNotes());
|
||||
|
||||
XSLFNotes notesSlide = ppt.getNotesSlide(slide1);
|
||||
assertNotNull(ppt.getNotesMaster());
|
||||
assertNotNull(notesSlide);
|
||||
|
||||
String note = null;
|
||||
for (XSLFTextShape shape : notesSlide.getPlaceholders()) {
|
||||
if (shape.getTextType() == Placeholder.BODY) {
|
||||
shape.setText("New Note");
|
||||
note = shape.getText();
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertNotNull(note);
|
||||
assertEquals("New Note", note);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addNote() {
|
||||
|
||||
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("sample.pptx");
|
||||
|
||||
XSLFSlide slide = ppt.createSlide();
|
||||
XSLFNotes notesSlide = ppt.getNotesSlide(slide);
|
||||
assertNotNull(notesSlide);
|
||||
|
||||
String note = null;
|
||||
for (XSLFTextShape shape : notesSlide.getPlaceholders()) {
|
||||
if (shape.getTextType() == Placeholder.BODY) {
|
||||
shape.setText("New Note");
|
||||
note = shape.getText();
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertNotNull(note);
|
||||
assertEquals("New Note", note);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void replaceNotes() {
|
||||
|
||||
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("sample.pptx");
|
||||
|
||||
for (XSLFSlide slide : ppt.getSlides()) {
|
||||
assertNotNull(slide.getNotes());
|
||||
|
||||
XSLFNotes notesSlide = ppt.getNotesSlide(slide);
|
||||
assertNotNull(notesSlide);
|
||||
|
||||
String note = null;
|
||||
for (XSLFTextShape shape : notesSlide.getPlaceholders()) {
|
||||
if (shape.getTextType() == Placeholder.BODY) {
|
||||
shape.setText("New Note");
|
||||
note = shape.getText();
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertNotNull(note);
|
||||
assertEquals("New Note", note);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user