- /*
- * 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.
- */
-
- /* $Id$ */
-
- package org.apache.fop.render.rtf.rtflib.rtfdoc;
-
- // Java
- import java.io.IOException;
- import java.io.Writer;
- import java.util.Iterator;
- import java.util.List;
- import java.util.ListIterator;
-
- // FOP
- import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfExternalGraphic;
-
- /**
- * Class which contains a linear text run. It has methods to add attributes,
- * text, paragraph breaks....
- * @author Peter Herweg, pherweg@web.de
- */
- public class RtfTextrun extends RtfContainer {
- private boolean bSuppressLastPar = false;
- private RtfListItem rtfListItem;
-
- /** Manager for handling space-* property. */
- private RtfSpaceManager rtfSpaceManager = new RtfSpaceManager();
-
- /** Class which represents the opening of a RTF group mark.*/
- private class RtfOpenGroupMark extends RtfElement {
-
- RtfOpenGroupMark(RtfContainer parent, Writer w, RtfAttributes attr)
- throws IOException {
- super(parent, w, attr);
- }
-
- /**
- * @return true if this element would generate no "useful" RTF content
- */
- public boolean isEmpty() {
- return false;
- }
-
- /**
- * write RTF code of all our children
- * @throws IOException for I/O problems
- */
- protected void writeRtfContent() throws IOException {
- writeGroupMark(true);
- writeAttributes(getRtfAttributes(), null);
- }
- }
-
- /** Class which represents the closing of a RTF group mark.*/
- private class RtfCloseGroupMark extends RtfElement {
-
- RtfCloseGroupMark(RtfContainer parent, Writer w)
- throws IOException {
- super(parent, w);
- }
-
- /**
- * @return true if this element would generate no "useful" RTF content
- */
- public boolean isEmpty() {
- return false;
- }
-
- /**
- * write RTF code of all our children
- * @throws IOException for I/O problems
- */
- protected void writeRtfContent() throws IOException {
- writeGroupMark(false);
- }
- }
-
- /** Class which represents a paragraph break.*/
- private class RtfParagraphBreak extends RtfElement {
-
- RtfParagraphBreak(RtfContainer parent, Writer w)
- throws IOException {
- super(parent, w);
- }
-
- /**
- * @return true if this element would generate no "useful" RTF content
- */
- public boolean isEmpty() {
- return false;
- }
-
- /**
- * write RTF code of all our children
- * @throws IOException for I/O problems
- */
- protected void writeRtfContent() throws IOException {
- writeControlWord("par");
- }
- }
-
- /** Create an RTF container as a child of given container */
- RtfTextrun(RtfContainer parent, Writer w, RtfAttributes attrs) throws IOException {
- super(parent, w, attrs);
- }
-
-
- /**
- * Adds instance of <code>OpenGroupMark</code> as a child with attributes.
- *
- * @param attrs attributes to add
- * @throws IOException for I/O problems
- */
- private void addOpenGroupMark(RtfAttributes attrs) throws IOException {
- RtfOpenGroupMark r = new RtfOpenGroupMark(this, writer, attrs);
- }
-
- /**
- * Adds instance of <code>CloseGroupMark</code> as a child.
- *
- * @throws IOException for I/O problems
- */
- private void addCloseGroupMark() throws IOException {
- RtfCloseGroupMark r = new RtfCloseGroupMark(this, writer);
- }
-
- /**
- * Pushes block attributes, notifies all opened blocks about pushing block
- * attributes, adds <code>OpenGroupMark</code> as a child.
- *
- * @param attrs the block attributes to push
- * @throws IOException for I/O problems
- */
- public void pushBlockAttributes(RtfAttributes attrs) throws IOException {
- rtfSpaceManager.stopUpdatingSpaceBefore();
- RtfSpaceSplitter splitter = rtfSpaceManager.pushRtfSpaceSplitter(attrs);
- addOpenGroupMark(splitter.getCommonAttributes());
- }
-
- /**
- * Pops block attributes, notifies all opened blocks about pushing block
- * attributes, adds <code>CloseGroupMark</code> as a child.
- *
- * @throws IOException for I/O problems
- */
- public void popBlockAttributes() throws IOException {
- rtfSpaceManager.popRtfSpaceSplitter();
- rtfSpaceManager.stopUpdatingSpaceBefore();
- addCloseGroupMark();
- }
-
- /**
- * Pushes inline attributes.
- *
- * @param attrs the inline attributes to push
- * @throws IOException for I/O problems
- */
- public void pushInlineAttributes(RtfAttributes attrs) throws IOException {
- rtfSpaceManager.pushInlineAttributes(attrs);
- addOpenGroupMark(attrs);
- }
-
- /**
- * Inserts a page number citation.
- * @param refId the identifier being referenced
- * @throws IOException for I/O problems
- */
- public void addPageNumberCitation(String refId) throws IOException {
- RtfPageNumberCitation r = new RtfPageNumberCitation(this, writer, refId);
- }
-
- /**
- * Pop inline attributes.
- *
- * @throws IOException for I/O problems
- */
- public void popInlineAttributes() throws IOException {
- rtfSpaceManager.popInlineAttributes();
- addCloseGroupMark();
- }
-
- /**
- * Add string to children list.
- *
- * @param s string to add
- * @throws IOException for I/O problems
- */
- public void addString(String s) throws IOException {
- if (s.equals("")) {
- return;
- }
- RtfAttributes attrs = rtfSpaceManager.getLastInlineAttribute();
- //add RtfSpaceSplitter to inherit accumulated space
- rtfSpaceManager.pushRtfSpaceSplitter(attrs);
- rtfSpaceManager.setCandidate(attrs);
- RtfString r = new RtfString(this, writer, s);
- rtfSpaceManager.popRtfSpaceSplitter();
- }
-
- /**
- * Inserts a footnote.
- *
- * @return inserted footnote
- * @throws IOException for I/O problems
- */
- public RtfFootnote addFootnote() throws IOException {
- return new RtfFootnote(this, writer);
- }
-
- /**
- * Inserts paragraph break before all close group marks.
- *
- * @throws IOException for I/O problems
- */
- public void addParagraphBreak() throws IOException {
- // get copy of children list
- List children = getChildren();
-
- // delete all previous CloseGroupMark
- int deletedCloseGroupCount = 0;
-
- ListIterator lit = children.listIterator(children.size());
- while (lit.hasPrevious()
- && (lit.previous() instanceof RtfCloseGroupMark)) {
- lit.remove();
- deletedCloseGroupCount++;
- }
-
- if (children.size() != 0) {
- // add paragraph break and restore all deleted close group marks
- setChildren(children);
- new RtfParagraphBreak(this, writer);
- for (int i = 0; i < deletedCloseGroupCount; i++) {
- addCloseGroupMark();
- }
- }
- }
-
- /**
- * Inserts a leader.
- * @param attrs Attributes for the leader
- * @throws IOException for I/O problems
- */
- public void addLeader(RtfAttributes attrs) throws IOException {
- new RtfLeader(this, writer, attrs);
- }
-
- /**
- * Inserts a page number.
- * @param attr Attributes for the page number to insert.
- * @throws IOException for I/O problems
- */
- public void addPageNumber(RtfAttributes attr) throws IOException {
- RtfPageNumber r = new RtfPageNumber(this, writer, attr);
- }
-
- /**
- * Inserts a hyperlink.
- * @param attr Attributes for the hyperlink to insert.
- * @return inserted hyperlink
- * @throws IOException for I/O problems
- */
- public RtfHyperLink addHyperlink(RtfAttributes attr) throws IOException {
- return new RtfHyperLink(this, writer, attr);
- }
-
- /**
- * Inserts a bookmark.
- * @param id Id for the inserted bookmark
- * @throws IOException for I/O problems
- */
- public void addBookmark(String id) throws IOException {
- if (id != "") {
- // if id is not empty, add boormark
- new RtfBookmark(this, writer, id);
- }
- }
-
- /**
- * Inserts an image.
- * @return inserted image
- * @throws IOException for I/O problems
- */
- public RtfExternalGraphic newImage() throws IOException {
- return new RtfExternalGraphic(this, writer);
- }
-
- /**
- * Adds a new RtfTextrun to the given container if necessary, and returns it.
- * @param container RtfContainer, which is the parent of the returned RtfTextrun
- * @param writer Writer of the given RtfContainer
- * @param attrs RtfAttributes which are to write at the beginning of the RtfTextrun
- * @return new or existing RtfTextrun object.
- * @throws IOException for I/O problems
- */
- public static RtfTextrun getTextrun(RtfContainer container, Writer writer, RtfAttributes attrs)
- throws IOException {
-
- List list = container.getChildren();
-
- if (list.size() == 0) {
- //add a new RtfTextrun
- RtfTextrun textrun = new RtfTextrun(container, writer, attrs);
- list.add(textrun);
-
- return textrun;
- }
-
- Object obj = list.get(list.size() - 1);
-
- if (obj instanceof RtfTextrun) {
- //if the last child is a RtfTextrun, return it
- return (RtfTextrun) obj;
- }
-
- //add a new RtfTextrun as the last child
- RtfTextrun textrun = new RtfTextrun(container, writer, attrs);
- list.add(textrun);
-
- return textrun;
- }
-
- /**
- * specify, if the last paragraph control word (\par) should be suppressed.
- * @param bSuppress true, if the last \par should be suppressed
- */
- public void setSuppressLastPar(boolean bSuppress) {
- bSuppressLastPar = bSuppress;
- }
-
- /**
- * write RTF code of all our children
- * @throws IOException for I/O problems
- */
- protected void writeRtfContent() throws IOException {
- /**
- *TODO: The textrun's children are iterated twice:
- * 1. To determine the last RtfParagraphBreak
- * 2. To write the children
- * Maybe this can be done more efficient.
- */
-
- boolean bHasTableCellParent =
- this.getParentOfClass(RtfTableCell.class) != null;
- RtfAttributes attrBlockLevel = new RtfAttributes();
-
- //determine, if this RtfTextrun is the last child of its parent
- boolean bLast = false;
- for (Iterator it = parent.getChildren().iterator(); it.hasNext();) {
- if (it.next() == this) {
- bLast = !it.hasNext();
- break;
- }
- }
-
- //get last RtfParagraphBreak, which is not followed by any visible child
- RtfParagraphBreak lastParagraphBreak = null;
- if (bLast) {
- for (Iterator it = getChildren().iterator(); it.hasNext();) {
- final RtfElement e = (RtfElement)it.next();
- if (e instanceof RtfParagraphBreak) {
- lastParagraphBreak = (RtfParagraphBreak)e;
- } else {
- if (!(e instanceof RtfOpenGroupMark)
- && !(e instanceof RtfCloseGroupMark)
- && e.isEmpty()) {
- lastParagraphBreak = null;
- }
- }
- }
- }
-
- //may contain for example \intbl
- writeAttributes(attrib, null);
-
- if (rtfListItem != null) {
- rtfListItem.getRtfListStyle().writeParagraphPrefix(this);
- }
-
- //write all children
- boolean bPrevPar = false;
- boolean bFirst = true;
- for (Iterator it = getChildren().iterator(); it.hasNext();) {
- final RtfElement e = (RtfElement)it.next();
- final boolean bRtfParagraphBreak = (e instanceof RtfParagraphBreak);
-
- if (bHasTableCellParent) {
- attrBlockLevel.set(e.getRtfAttributes());
- }
-
-
- /**
- * -Write RtfParagraphBreak only, if the previous visible child
- * was't also a RtfParagraphBreak.
- * -Write RtfParagraphBreak only, if it is not the first visible
- * child.
- * -If the RtfTextrun is the last child of its parent, write a
- * RtfParagraphBreak only, if it is not the last child.
- */
- boolean bHide = false;
- bHide = bRtfParagraphBreak;
- bHide = bHide
- && (bPrevPar
- || bFirst
- || (bSuppressLastPar && bLast && lastParagraphBreak != null
- && e == lastParagraphBreak));
-
- if (!bHide) {
- newLine();
- e.writeRtf();
-
- if (rtfListItem != null && e instanceof RtfParagraphBreak) {
- rtfListItem.getRtfListStyle().writeParagraphPrefix(this);
- }
- }
-
- if (e instanceof RtfParagraphBreak) {
- bPrevPar = true;
- } else if (e instanceof RtfCloseGroupMark) {
- //do nothing
- } else if (e instanceof RtfOpenGroupMark) {
- //do nothing
- } else {
- bPrevPar = bPrevPar && e.isEmpty();
- bFirst = bFirst && e.isEmpty();
- }
- } //for (Iterator it = ...)
-
- //
- if (bHasTableCellParent) {
- writeAttributes(attrBlockLevel, null);
- }
-
- }
-
- /**
- * Set the parent list-item of the textrun.
- *
- * @param listItem parent list-item of the textrun
- */
- public void setRtfListItem(RtfListItem listItem) {
- rtfListItem = listItem;
- }
-
- /**
- * Gets the parent list-item of the textrun.
- *
- * @return parent list-item of the textrun
- */
- public RtfListItem getRtfListItem() {
- return rtfListItem;
- }
- }
-
|