All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.odftoolkit.simple.PresentationDocument Maven / Gradle / Ivy

There is a newer version: 0.8.2-incubating
Show newest version
/************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 * 
 * Copyright 2008, 2010 Oracle and/or its affiliates. All rights reserved.
 * 
 * Use is subject to license terms.
 * 
 * Licensed 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. You can also
 * obtain a copy of the License at http://odftoolkit.org/docs/license.txt
 * 
 * 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.odftoolkit.simple;

import java.awt.Rectangle;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.xpath.XPathConstants;

import org.odftoolkit.odfdom.dom.OdfContentDom;
import org.odftoolkit.odfdom.dom.OdfDocumentNamespace;
import org.odftoolkit.odfdom.dom.attribute.text.TextAnchorTypeAttribute;
import org.odftoolkit.odfdom.dom.element.draw.DrawFrameElement;
import org.odftoolkit.odfdom.dom.element.draw.DrawPageElement;
import org.odftoolkit.odfdom.dom.element.draw.DrawPageThumbnailElement;
import org.odftoolkit.odfdom.dom.element.office.OfficePresentationElement;
import org.odftoolkit.odfdom.dom.element.presentation.PresentationNotesElement;
import org.odftoolkit.odfdom.pkg.MediaType;
import org.odftoolkit.odfdom.pkg.OdfElement;
import org.odftoolkit.odfdom.pkg.OdfFileDom;
import org.odftoolkit.odfdom.pkg.OdfPackage;
import org.odftoolkit.odfdom.type.CellRangeAddressList;
import org.odftoolkit.simple.chart.AbstractChartContainer;
import org.odftoolkit.simple.chart.Chart;
import org.odftoolkit.simple.chart.ChartContainer;
import org.odftoolkit.simple.chart.DataSet;
import org.odftoolkit.simple.presentation.Slide;
import org.odftoolkit.simple.presentation.Notes.NotesBuilder;
import org.odftoolkit.simple.presentation.Slide.SlideBuilder;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * This class represents an empty ODF presentation.
 */
public class PresentationDocument extends Document implements ChartContainer{

	private static final String EMPTY_PRESENTATION_DOCUMENT_PATH = "/OdfPresentationDocument.odp";
	static final Resource EMPTY_PRESENTATION_DOCUMENT_RESOURCE = new Resource(EMPTY_PRESENTATION_DOCUMENT_PATH);
	private final SlideBuilder slideBuilder;
	private final NotesBuilder notesBuilder;
	private ChartContainerImpl chartContainerImpl;
	
	/**
	 * It represents the defined values of presentation:class. The
	 * presentation:class attribute classifies presentation shapes by their
	 * usage within a draw page.
	 * 
	 * @since 0.5
	 */
	public static enum PresentationClass {
		/**
		 * presentation charts are standard object shapes.
		 */
		CHAT("chart"),
		/**
		 * presentation graphics are standard graphic shapes.
		 */
		GRAPHIC("graphic"),
		/**
		 * presentation handouts are placeholder for the drawing page in a
		 * handout page.
		 */
		HANDOUT("handout"),
		/**
		 * presentation notes are used on notes pages.
		 */
		NOTES("notes"),
		/**
		 * presentation objects are standard object shapes.
		 */
		OBJECTS("object"),
		/**
		 * presentation organization charts are standard object shapes.
		 */
		ORGCHART("orgchart"),
		/**
		 * outlines are standard text shapes
		 */
		OUTLINE("outline"),
		/**
		 * presentation pages are used on notes pages
		 */
		PAGE("page"),
		/**
		 * subtitles are standard text shapes
		 */
		SUBTITLE("subtitle"),
		/**
		 * presentation tables are standard object shapes
		 */
		TABLE("table"),
		/**
		 * presentation texts are standard text shapes
		 */
		TEXT("text"),
		/**
		 * titles are standard text shapes
		 */
		TITLE("title"),
		/**
		 * drawing shape is used as a date and/or time shape. Date and Time
		 * shapes are standard text shapes.
		 */
		DATETIME("date-time"),
		/**
		 * drawing shape is used as a footer. Footer shapes are standard text
		 * shapes.
		 */
		FOOTER("footer"),
		/**
		 * drawing shape is used as a header. Header shapes are standard text
		 * shapes.
		 */
		HEADER("header"),
		/**
		 * drawing shape is used as a page number shape. Page Number shapes are
		 * standard text shapes.
		 */
		PAGENUMBER("page-number");

		private String value;

		PresentationClass(String aClass) {
			value = aClass;
		}

		@Override
		public String toString() {
			return value;
		}

		public static PresentationClass enumValueOf(String aValue) {
			if ((aValue == null) || (aValue.length() == 0))
				return null;

			for (PresentationClass aIter : values()) {
				if (aValue.equals(aIter.toString())) {
					return aIter;
				}
			}
			throw new RuntimeException("Unsupported Presentation Class!");
		}
	}
	
	/**
	 * This enum contains all possible media types of PresentationDocument
	 * documents.
	 */
	public enum OdfMediaType implements MediaType {

		PRESENTATION(Document.OdfMediaType.PRESENTATION), PRESENTATION_TEMPLATE(
				Document.OdfMediaType.PRESENTATION_TEMPLATE);
		private final Document.OdfMediaType mMediaType;

		OdfMediaType(Document.OdfMediaType mediaType) {
			this.mMediaType = mediaType;
		}

		/**
		 * @return the ODF mediatype of this document
		 */
		public Document.OdfMediaType getOdfMediaType() {
			return mMediaType;
		}

		/**
		 * @return the mediatype of this document
		 */
		public String getMediaTypeString() {
			return mMediaType.getMediaTypeString();
		}

		/**
		 * @return the ODF filesuffix of this document
		 */
		public String getSuffix() {
			return mMediaType.getSuffix();
		}

		/**
		 * 
		 * @param mediaType
		 *            string defining an ODF document
		 * @return the according OdfMediatype encapuslating the given string and
		 *         the suffix
		 */
		public static Document.OdfMediaType getOdfMediaType(String mediaType) {
			return Document.OdfMediaType.getOdfMediaType(mediaType);
		}
	}

	/**
	 * Creates an empty presentation document.
	 * 
	 * @return ODF presentation document based on a default template
	 * @throws java.lang.Exception
	 *             - if the document could not be created
	 */
	public static PresentationDocument newPresentationDocument() throws Exception {
		return (PresentationDocument) Document.loadTemplate(EMPTY_PRESENTATION_DOCUMENT_RESOURCE,
				Document.OdfMediaType.PRESENTATION);
	}

	/**
	 * Creates an empty presentation template.
	 * 
	 * @return ODF presentation template based on a default
	 * @throws Exception
	 *             - if the template could not be created
	 */
	public static PresentationDocument newPresentationTemplateDocument() throws Exception {
		PresentationDocument doc = (PresentationDocument) Document.loadTemplate(EMPTY_PRESENTATION_DOCUMENT_RESOURCE,
				Document.OdfMediaType.PRESENTATION_TEMPLATE);
		doc.changeMode(OdfMediaType.PRESENTATION_TEMPLATE);
		return doc;
	}

	/**
	 * To avoid data duplication a new document is only created, if not already
	 * opened. A document is cached by this constructor using the internalpath
	 * as key.
	 */
	protected PresentationDocument(OdfPackage pkg, String internalPath, PresentationDocument.OdfMediaType odfMediaType) {
		super(pkg, internalPath, odfMediaType.mMediaType);
		slideBuilder = new SlideBuilder(this);
		notesBuilder = new NotesBuilder(this);
	}

	/**
	 * Creates an PresentationDocument from the OpenDocument provided by a
	 * resource Stream.
	 * 
	 * 

* Since an InputStream does not provide the arbitrary (non sequentiell) * read access needed by PresentationDocument, the InputStream is cached. * This usually takes more time compared to the other createInternalDocument * methods. An advantage of caching is that there are no problems * overwriting an input file. *

* *

* If the resource stream is not a ODF presentation document, * ClassCastException might be thrown. *

* * @param inputStream * - the InputStream of the ODF presentation document. * @return the presentation document created from the given InputStream * @throws java.lang.Exception * - if the document could not be created. */ public static PresentationDocument loadDocument(InputStream inputStream) throws Exception { return (PresentationDocument) Document.loadDocument(inputStream); } /** * Loads an PresentationDocument from the provided path. * *

* PresentationDocument relies on the file being available for read access * over the whole lifecycle of PresentationDocument. *

* *

* If the resource stream is not a ODF presentation document, * ClassCastException might be thrown. *

* * @param documentPath * - the path from where the document can be loaded * @return the presentation document from the given path or NULL if the * media type is not supported by SIMPLE. * @throws java.lang.Exception * - if the document could not be created. */ public static PresentationDocument loadDocument(String documentPath) throws Exception { return (PresentationDocument) Document.loadDocument(documentPath); } /** * Creates an PresentationDocument from the OpenDocument provided by a File. * *

* PresentationDocument relies on the file being available for read access * over the whole lifecycle of PresentationDocument. *

* *

* If the resource stream is not a ODF presentation document, * ClassCastException might be thrown. *

* * @param file * - a file representing the ODF presentation document. * @return the presentation document created from the given File * @throws java.lang.Exception * - if the document could not be created. */ public static PresentationDocument loadDocument(File file) throws Exception { return (PresentationDocument) Document.loadDocument(file); } /** * Get the content root of a presentation document. * * @return content root, representing the office:presentation tag * @throws Exception * if the file DOM could not be created. */ @Override public OfficePresentationElement getContentRoot() throws Exception { return super.getContentRoot(OfficePresentationElement.class); } /** * Switches this instance to the given type. This method can be used to e.g. * convert a document instance to a template and vice versa. Changes take * affect in the package when saving the document. * * @param type * the compatible ODF mediatype. */ public void changeMode(OdfMediaType type) { setOdfMediaType(type.mMediaType); } private boolean hasCheckSlideName = false; /** * Return the slide builder of this document. Every presentation document * has a slide builder. * * @return the slide builder of this document. * @since 0.3.5 */ public SlideBuilder getSlideBuilder() { return slideBuilder; } /** * Return the notes builder of this document. Every presentation document * has a notes builder. * * @return the notes builder of this document. * @since 0.3.5 */ public NotesBuilder getNotesBuilder() { return notesBuilder; } /** * Return the slide at a specified position in this presentation. Return * null if the index is out of range. * * @param index * the index of the slide to be returned * @return a draw slide at the specified position */ public Slide getSlideByIndex(int index) { checkAllSlideName(); OfficePresentationElement contentRoot = null; try { contentRoot = getContentRoot(); } catch (Exception e) { Logger.getLogger(PresentationDocument.class.getName()).log(Level.SEVERE, null, e); return null; } NodeList slideNodes = contentRoot.getElementsByTagNameNS(OdfDocumentNamespace.DRAW.getUri(), "page"); if ((index >= slideNodes.getLength()) || (index < 0)) { return null; } DrawPageElement slideElement = (DrawPageElement) slideNodes.item(index); return Slide.getInstance(slideElement); } /** * Get the number of the slides in this presentation. * * @return the number of slides */ public int getSlideCount() { checkAllSlideName(); OfficePresentationElement contentRoot = null; try { contentRoot = getContentRoot(); } catch (Exception e) { Logger.getLogger(PresentationDocument.class.getName()).log(Level.SEVERE, null, e); return 0; } NodeList slideNodes = contentRoot.getElementsByTagNameNS(OdfDocumentNamespace.DRAW.getUri(), "page"); return slideNodes.getLength(); } /** * Return the slide which have a specified slide name in this presentation. *

* According to the odf specification "The draw:name attribute specifies a * name by which this element can be referenced. It is optional but if * present, must be unique within the document instance. If not present, an * application may generate a unique name." *

* If the name is null, then return null because all the slide must has its * own unique name. * * @param name * the specified slide name * @return the slide whose name equals to the specified name */ public Slide getSlideByName(String name) { checkAllSlideName(); if (name == null) { return null; } OfficePresentationElement contentRoot = null; try { contentRoot = getContentRoot(); } catch (Exception e) { Logger.getLogger(PresentationDocument.class.getName()).log(Level.SEVERE, null, e); return null; } NodeList slideNodes = contentRoot.getElementsByTagNameNS(OdfDocumentNamespace.DRAW.getUri(), "page"); for (int i = 0; i < slideNodes.getLength(); i++) { DrawPageElement slideElement = (DrawPageElement) slideNodes.item(i); Slide slide = Slide.getInstance(slideElement); String slideName = slide.getSlideName(); if (slideName.equals(name)) { return slide; } } return null; } // when access slide related method, this function should be called private void checkAllSlideName() { // check if this function is called or not if (hasCheckSlideName) { return; } List slideNameList = new ArrayList(); OfficePresentationElement contentRoot = null; try { contentRoot = getContentRoot(); } catch (Exception e) { Logger.getLogger(PresentationDocument.class.getName()).log(Level.SEVERE, null, e); return; } NodeList slideNodes = contentRoot.getElementsByTagNameNS(OdfDocumentNamespace.DRAW.getUri(), "page"); for (int i = 0; i < slideNodes.getLength(); i++) { DrawPageElement slideElement = (DrawPageElement) slideNodes.item(i); String slideName = slideElement.getDrawNameAttribute(); if ((slideName == null) || slideNameList.contains(slideName)) { slideName = "page" + (i + 1) + "-" + makeUniqueName(); slideElement.setDrawNameAttribute(slideName); } slideNameList.add(slideName); } hasCheckSlideName = true; } /** * Return a list iterator containing all slides in this presentation. * * @return a list iterator containing all slides in this presentation */ public Iterator getSlides() { checkAllSlideName(); OfficePresentationElement contentRoot = null; try { contentRoot = getContentRoot(); } catch (Exception e) { Logger.getLogger(PresentationDocument.class.getName()).log(Level.SEVERE, null, e); return null; } ArrayList slideList = new ArrayList(); NodeList slideNodes = contentRoot.getElementsByTagNameNS(OdfDocumentNamespace.DRAW.getUri(), "page"); for (int i = 0; i < slideNodes.getLength(); i++) { DrawPageElement slideElement = (DrawPageElement) slideNodes.item(i); slideList.add(Slide.getInstance(slideElement)); } return slideList.iterator(); } /** * Delete the slide at a specified position in this presentation. * * @param index * the index of the slide that need to be delete *

* Throw IndexOutOfBoundsException if the slide index is out of * the presentation document slide count. * @return false if the operation was not successful */ public boolean deleteSlideByIndex(int index) { boolean success = true; checkAllSlideName(); OfficePresentationElement contentRoot = null; try { contentRoot = getContentRoot(); } catch (Exception e) { Logger.getLogger(PresentationDocument.class.getName()).log(Level.SEVERE, null, e); success = false; return success; } NodeList slideNodes = contentRoot.getElementsByTagNameNS(OdfDocumentNamespace.DRAW.getUri(), "page"); if ((index >= slideNodes.getLength()) || (index < 0)) { throw new IndexOutOfBoundsException( "the specified Index is out of slide count when call deleteSlideByIndex method."); } DrawPageElement slideElement = (DrawPageElement) slideNodes.item(index); // remove all the content of the current page // 1. the reference of the path that contained in this slide is 1, then // remove it // success &= deleteLinkedRef(slideElement); // 2.the reference of the style is 1, then remove it // in order to save time, do not delete the style here // success &= deleteStyleRef(slideElement); // these two methods have been merged into 1 method success &= removeElementLinkedResource(slideElement); // remove the current page element contentRoot.removeChild(slideElement); adjustNotePageNumber(index); return success; } /** * Delete all the slides with a specified name in this presentation. * * @param name * the name of the slide that need to be delete * @return false if the operation was not successful */ public boolean deleteSlideByName(String name) { boolean success = true; checkAllSlideName(); OfficePresentationElement contentRoot = null; try { contentRoot = getContentRoot(); } catch (Exception e) { Logger.getLogger(PresentationDocument.class.getName()).log(Level.SEVERE, null, e); success = false; return success; } Slide slide = getSlideByName(name); DrawPageElement slideElement = slide.getOdfElement(); // remove all the content of the current page // 1. the reference of the path that contained in this slide is 1, then // remove its success &= deleteLinkedRef(slideElement); // 2.the reference of the style is 1, then remove it // in order to save time, do not delete style here success &= deleteStyleRef(slideElement); // remove the current page element contentRoot.removeChild(slideElement); adjustNotePageNumber(0); return success; } /** * Make a copy of the slide at a specified position to another position in * this presentation. The original slide which at the dest index and after * the dest index will move after. *

* * @param source * the source position of the slide need to be copied * @param dest * the destination position of the slide need to be copied * @param newName * the new name of the copied slide * @return the new slide at the destination position with the specified * name, and it has the same content with the slide at the source * position. *

* Throw IndexOutOfBoundsException if the slide index is out of the * presentation document slide count. If copy the slide at the end * of document, destIndex should set the same value with the slide * count. */ public Slide copySlide(int source, int dest, String newName) { checkAllSlideName(); OfficePresentationElement contentRoot = null; try { contentRoot = getContentRoot(); } catch (Exception e) { Logger.getLogger(PresentationDocument.class.getName()).log(Level.SEVERE, null, e); return null; } NodeList slideList = contentRoot.getElementsByTagNameNS(OdfDocumentNamespace.DRAW.getUri(), "page"); int slideCount = slideList.getLength(); if ((source < 0) || (source >= slideCount) || (dest < 0) || (dest > slideCount)) { throw new IndexOutOfBoundsException("the specified Index is out of slide count when call copySlide method."); } DrawPageElement sourceSlideElement = (DrawPageElement) slideList.item(source); DrawPageElement cloneSlideElement = (DrawPageElement) sourceSlideElement.cloneNode(true); cloneSlideElement.setDrawNameAttribute(newName); if (dest == slideCount) { contentRoot.appendChild(cloneSlideElement); } else { DrawPageElement refSlide = (DrawPageElement) slideList.item(dest); contentRoot.insertBefore(cloneSlideElement, refSlide); } adjustNotePageNumber(Math.min(source, dest)); // in case that the appended new slide have the same name with the // original slide hasCheckSlideName = false; checkAllSlideName(); return Slide.getInstance(cloneSlideElement); } /** * Move the slide at a specified position to the destination position. * * @param source * the current index of the slide that need to be moved * @param dest * The index of the destination position before the move action *

* Throw IndexOutOfBoundsException if the slide index is out of * the presentation document slide count. */ public void moveSlide(int source, int dest) { checkAllSlideName(); OfficePresentationElement contentRoot = null; try { contentRoot = getContentRoot(); } catch (Exception e) { Logger.getLogger(PresentationDocument.class.getName()).log(Level.SEVERE, null, e); return; } NodeList slideList = contentRoot.getElementsByTagNameNS(OdfDocumentNamespace.DRAW.getUri(), "page"); int slideCount = slideList.getLength(); if ((source < 0) || (source >= slideCount) || (dest < 0) || (dest > slideCount)) { throw new IndexOutOfBoundsException("the specified Index is out of slide count when call moveSlide method."); } DrawPageElement sourceSlide = (DrawPageElement) slideList.item(source); if (dest == slideCount) { contentRoot.appendChild(sourceSlide); } else { DrawPageElement refSlide = (DrawPageElement) slideList.item(dest); contentRoot.insertBefore(sourceSlide, refSlide); } adjustNotePageNumber(Math.min(source, dest)); } private Node cloneForeignElement_(Node element, OdfFileDom dom, boolean deep) { checkAllSlideName(); return cloneForeignElement(element, dom, deep); } /** * Append all the slides of the specified presentation document to the * current document. * * @param srcDoc * the specified PresentationDocument that need to * be appended */ public void appendPresentation(PresentationDocument srcDoc) { checkAllSlideName(); OfficePresentationElement contentRoot = null; OdfFileDom contentDom = null; OfficePresentationElement srcContentRoot = null; try { contentRoot = getContentRoot(); contentDom = getContentDom(); srcContentRoot = srcDoc.getContentRoot(); } catch (Exception e) { Logger.getLogger(PresentationDocument.class.getName()).log(Level.SEVERE, null, e); } NodeList slideList = contentRoot.getElementsByTagNameNS(OdfDocumentNamespace.DRAW.getUri(), "page"); int slideNum = slideList.getLength(); // clone the srcContentRoot, and make a modification on this clone node. OfficePresentationElement srcCloneContentRoot = (OfficePresentationElement) srcContentRoot.cloneNode(true); // copy all the referred xlink:href here copyLinkedRefInBatch(srcCloneContentRoot, srcDoc); // copy all the referred style definition here copyForeignStyleRef(srcCloneContentRoot, srcDoc); Node child = srcCloneContentRoot.getFirstChild(); while (child != null) { Node cloneElement = cloneForeignElement_(child, contentDom, true); contentRoot.appendChild(cloneElement); child = child.getNextSibling(); } adjustNotePageNumber(slideNum - 1); // in case that the appended new slide have the same name with the // original slide hasCheckSlideName = false; checkAllSlideName(); } /** * Make a copy of slide which locates at the specified position of the * source presentation document and insert it to the current presentation * document at the new position. The original slide which at the dest index * and after the dest index will move after. * * @param destIndex * the new position of the copied slide in the current document * @param srcDoc * the source document of the copied slide * @param srcIndex * the slide index of the source document that need to be copied * @return the new slide which has the same content with the source slide *

* Throw IndexOutOfBoundsException if the slide index is out of the * presentation document slide count If insert the foreign slide at * the end of document, destIndex should set the same value with the * slide count of the current presentation document. */ public Slide copyForeignSlide(int destIndex, PresentationDocument srcDoc, int srcIndex) { checkAllSlideName(); OfficePresentationElement contentRoot = null; OdfFileDom contentDom = null; try { contentRoot = getContentRoot(); contentDom = getContentDom(); } catch (Exception e) { Logger.getLogger(PresentationDocument.class.getName()).log(Level.SEVERE, null, e); return null; } NodeList slideList = contentRoot.getElementsByTagNameNS(OdfDocumentNamespace.DRAW.getUri(), "page"); int slideCount = slideList.getLength(); if ((destIndex < 0) || (destIndex > slideCount)) { throw new IndexOutOfBoundsException( "the specified Index is out of slide count when call copyForeignSlide method."); } Slide sourceSlide = srcDoc.getSlideByIndex(srcIndex); DrawPageElement sourceSlideElement = sourceSlide.getOdfElement(); // clone the sourceSlideEle, and make a modification on this clone node. DrawPageElement sourceCloneSlideElement = (DrawPageElement) sourceSlideElement.cloneNode(true); // copy all the referred xlink:href here copyLinkedRefInBatch(sourceCloneSlideElement, srcDoc); // copy all the referred style definition here copyForeignStyleRef(sourceCloneSlideElement, srcDoc); // clone the sourceCloneSlideEle, and this cloned element should in the // current dom tree DrawPageElement cloneSlideElement = (DrawPageElement) cloneForeignElement_(sourceCloneSlideElement, contentDom, true); if (destIndex == slideCount) { contentRoot.appendChild(cloneSlideElement); } else { DrawPageElement refSlide = (DrawPageElement) slideList.item(destIndex); contentRoot.insertBefore(cloneSlideElement, refSlide); } adjustNotePageNumber(destIndex); // in case that the appended new slide have the same name with the // original slide hasCheckSlideName = false; checkAllSlideName(); return Slide.getInstance(cloneSlideElement); } /** * New a slide at the specified position with the specified name, and use * the specified slide template. See OdfDrawPage.SlideLayout. *

* If index is invalid, such as larger than the current document slide * number or is negative, then append the new slide at the end of the * document. *

* The slide name can be null. * * @param index * the new slide position * @param name * the new slide name * @param slideLayout * the new slide template * @return the new slide which locate at the specified position with the * specified name and apply the specified slide template. If * slideLayout is null, then use the default slide template which is * a blank slide. *

* Throw IndexOutOfBoundsException if index is out of the * presentation document slide count. */ public Slide newSlide(int index, String name, Slide.SlideLayout slideLayout) { checkAllSlideName(); OfficePresentationElement contentRoot = null; try { contentRoot = getContentRoot(); } catch (Exception e) { Logger.getLogger(PresentationDocument.class.getName()).log(Level.SEVERE, null, e); return null; } NodeList slideList = contentRoot.getElementsByTagNameNS(OdfDocumentNamespace.DRAW.getUri(), "page"); int slideCount = slideList.getLength(); if ((index < 0) || (index > slideCount)) { throw new IndexOutOfBoundsException("the specified Index is out of slide count when call newSlide method."); } // if insert page at the beginning of the document, // get the next page style as the new page style // else get the previous page style as the new page style DrawPageElement refStyleSlide = null; int refSlideIndex = 0; if (index > 0) { refSlideIndex = index - 1; } refStyleSlide = (DrawPageElement) slideList.item(refSlideIndex); String masterPageStyleName = "Default"; String masterName = refStyleSlide.getDrawMasterPageNameAttribute(); if (masterName != null) { masterPageStyleName = masterName; } DrawPageElement newSlideElement = contentRoot.newDrawPageElement(masterPageStyleName); newSlideElement.setDrawNameAttribute(name); String drawStyleName = refStyleSlide.getDrawStyleNameAttribute(); if (drawStyleName != null) { newSlideElement.setDrawStyleNameAttribute(drawStyleName); } String pageLayoutName = refStyleSlide.getPresentationPresentationPageLayoutNameAttribute(); if (pageLayoutName != null) { newSlideElement.setPresentationPresentationPageLayoutNameAttribute(pageLayoutName); } setSlideLayout(newSlideElement, slideLayout); // insert notes page NodeList noteNodes = refStyleSlide.getElementsByTagNameNS(OdfDocumentNamespace.PRESENTATION.getUri(), "notes"); if (noteNodes.getLength() > 0) { PresentationNotesElement notePage = (PresentationNotesElement) noteNodes.item(0); PresentationNotesElement cloneNotePage = (PresentationNotesElement) notePage.cloneNode(true); newSlideElement.appendChild(cloneNotePage); } if (index < slideCount) { DrawPageElement refSlide = (DrawPageElement) slideList.item(index); contentRoot.insertBefore(newSlideElement, refSlide); } adjustNotePageNumber(index); // in case that the appended new slide have the same name with the // original slide hasCheckSlideName = false; checkAllSlideName(); return Slide.getInstance(newSlideElement); } public Chart createChart(String title, DataSet dataset, Rectangle rect) { return getChartContainerImpl().createChart(title, dataset, rect); } public Chart createChart(String title, SpreadsheetDocument document, CellRangeAddressList cellRangeAddr, boolean firstRowAsLabel, boolean firstColumnAsLabel, boolean rowAsDataSeries, Rectangle rect) { return getChartContainerImpl().createChart(title, document, cellRangeAddr, firstRowAsLabel, firstColumnAsLabel, rowAsDataSeries, rect); } public Chart createChart(String title, String[] labels, String[] legends, double[][] data, Rectangle rect) { return getChartContainerImpl().createChart(title, labels, legends, data, rect); } public void deleteChartById(String chartId) { getChartContainerImpl().deleteChartById(chartId); } public void deleteChartByTitle(String title) { getChartContainerImpl().deleteChartByTitle(title); } public Chart getChartById(String chartId) { return getChartContainerImpl().getChartById(chartId); } public List getChartByTitle(String title) { return getChartContainerImpl().getChartByTitle(title); } public int getChartCount() { return getChartContainerImpl().getChartCount(); } // when insert a slide, the note page for this slide is also inserted. // note page refer the slide index in order to show the corresponding slide // notes view // this function is used to adjust note page referred slide index since // startIndex // when the slide at startIndex has been delete or insert private void adjustNotePageNumber(int startIndex) { try { OfficePresentationElement contentRoot = getContentRoot(); NodeList slideList = contentRoot.getElementsByTagNameNS(OdfDocumentNamespace.DRAW.getUri(), "page"); for (int i = startIndex; i < getSlideCount(); i++) { DrawPageElement page = (DrawPageElement) slideList.item(i); NodeList noteNodes = page.getElementsByTagNameNS(OdfDocumentNamespace.PRESENTATION.getUri(), "notes"); if (noteNodes.getLength() > 0) { PresentationNotesElement notePage = (PresentationNotesElement) noteNodes.item(0); NodeList thumbnailList = notePage.getElementsByTagNameNS(OdfDocumentNamespace.DRAW.getUri(), "page-thumbnail"); if (thumbnailList.getLength() > 0) { DrawPageThumbnailElement thumbnail = (DrawPageThumbnailElement) thumbnailList.item(0); thumbnail.setDrawPageNumberAttribute(i + 1); } } } } catch (Exception e) { Logger.getLogger(PresentationDocument.class.getName()).log(Level.SEVERE, null, e); } } // covered element // , , // private void setSlideLayout(DrawPageElement page, Slide.SlideLayout slideLayout) { if (slideLayout == null) { slideLayout = Slide.SlideLayout.BLANK; } slideLayout.apply(page); } public OdfElement getTableContainerElement() { throw new UnsupportedOperationException("Presentation document is not supported to hold table directly."); } private ChartContainerImpl getChartContainerImpl() { if (chartContainerImpl == null) { chartContainerImpl = new ChartContainerImpl(this); } return chartContainerImpl; } private class ChartContainerImpl extends AbstractChartContainer { PresentationDocument sdoc; protected ChartContainerImpl(Document doc) { super(doc); sdoc = (PresentationDocument) doc; } protected DrawFrameElement getChartFrame() throws Exception { OdfContentDom contentDom2 = sdoc.getContentDom(); DrawFrameElement drawFrame = contentDom2.newOdfElement(DrawFrameElement.class); DrawPageElement lastPage = (DrawPageElement) contentDom2.getXPath().evaluate("//draw:page[last()]", contentDom2, XPathConstants.NODE); lastPage.appendChild(drawFrame); drawFrame.setTextAnchorTypeAttribute(TextAnchorTypeAttribute.Value.PAGE.toString()); return drawFrame; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy