001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /* $Id: RtfParagraph.java 426576 2006-07-28 15:44:37Z jeremias $ */
019:
020: package org.apache.fop.render.rtf.rtflib.rtfdoc;
021:
022: /*
023: * This file is part of the RTF library of the FOP project, which was originally
024: * created by Bertrand Delacretaz <bdelacretaz@codeconsult.ch> and by other
025: * contributors to the jfor project (www.jfor.org), who agreed to donate jfor to
026: * the FOP project.
027: */
028:
029: import java.io.Writer;
030: import java.io.IOException;
031: import java.util.List;
032:
033: /** Model of an RTF paragraph, which can contain RTF text elements.
034: * @author Bertrand Delacretaz bdelacretaz@codeconsult.ch
035: * @author Andreas Putz a.putz@skynamics.com
036: * @author Boris Poudérous, boris.pouderous@free.fr
037: */
038:
039: public class RtfParagraph extends RtfBookmarkContainerImpl implements
040: IRtfTextContainer, IRtfPageBreakContainer,
041: IRtfHyperLinkContainer, IRtfExternalGraphicContainer,
042: IRtfPageNumberContainer, IRtfPageNumberCitationContainer {
043: private RtfText text;
044: private RtfHyperLink hyperlink;
045: private RtfExternalGraphic externalGraphic;
046: private RtfPageNumber pageNumber;
047: private RtfPageNumberCitation pageNumberCitation;
048: // Above line added by Boris POUDEROUS on 2002/07/09
049: private boolean keepn = false;
050: private boolean resetProperties = false;
051:
052: /* needed for importing Rtf into FrameMaker
053: FrameMaker is not as forgiving as word in rtf
054: thus /pard/par must be written in a page break directly
055: after a table. /pard is probably needed in other places
056: also, this is just a hack to make FrameMaker import Jfor rtf
057: correctly */
058: private boolean writeForBreak = false;
059:
060: /** Set of attributes that must be copied at the start of a paragraph */
061: private static final String[] PARA_ATTRIBUTES = { "intbl" };
062:
063: /** Create an RTF paragraph as a child of given container with default attributes */
064: RtfParagraph(IRtfParagraphContainer parent, Writer w)
065: throws IOException {
066: super ((RtfContainer) parent, w);
067: }
068:
069: /** Create an RTF paragraph as a child of given container with given attributes */
070: RtfParagraph(IRtfParagraphContainer parent, Writer w,
071: RtfAttributes attr) throws IOException {
072: super ((RtfContainer) parent, w, attr);
073: }
074:
075: /**
076: * Accessor for the paragraph text
077: * @return the paragraph text
078: */
079: public String getText() {
080: return (text.getText());
081: }
082:
083: /** Set the keepn attribute for this paragraph */
084: public void setKeepn() {
085: this .keepn = true;
086: }
087:
088: /** Force reset properties */
089: public void setResetProperties() {
090: this .resetProperties = true;
091: }
092:
093: /**
094: * IRtfTextContainer requirement: return a copy of our attributes
095: * @return a copy of this paragraphs attributes
096: */
097: public RtfAttributes getTextContainerAttributes() {
098: if (attrib == null) {
099: return null;
100: }
101: return (RtfAttributes) this .attrib.clone();
102: }
103:
104: /**
105: * Overridden to write our attributes before our content
106: * @throws IOException for I/O problems
107: */
108: protected void writeRtfPrefix() throws IOException {
109:
110: //Reset paragraph properties if needed
111: if (resetProperties) {
112: writeControlWord("pard");
113: }
114:
115: /*
116: * Original comment said "do not write text attributes here, they are
117: * handled by RtfText." However, the text attributes appear to be
118: * relevant to paragraphs as well.
119: */
120: writeAttributes(attrib, RtfText.ATTR_NAMES);
121: writeAttributes(attrib, PARA_ATTRIBUTES);
122: // Added by Normand Masse
123: // Write alignment attributes after \intbl for cells
124: if (attrib.isSet("intbl") && mustWriteAttributes()) {
125: writeAttributes(attrib, RtfText.ALIGNMENT);
126: }
127:
128: //Set keepn if needed (Keep paragraph with the next paragraph)
129: if (keepn) {
130: writeControlWord("keepn");
131: }
132:
133: // start a group for this paragraph and write our own attributes if needed
134: if (mustWriteGroupMark()) {
135: writeGroupMark(true);
136: }
137:
138: if (mustWriteAttributes()) {
139: // writeAttributes(m_attrib, new String [] {"cs"});
140: // Added by Normand Masse
141: // If \intbl then attributes have already been written (see higher in method)
142: if (!attrib.isSet("intbl")) {
143: writeAttributes(attrib, RtfText.ALIGNMENT);
144: }
145: //this line added by Chris Scott, Westinghouse
146: writeAttributes(attrib, RtfText.BORDER);
147: writeAttributes(attrib, RtfText.INDENT);
148: writeAttributes(attrib, RtfText.TABS);
149: if (writeForBreak) {
150: writeControlWord("pard\\par");
151: }
152: }
153:
154: }
155:
156: /**
157: * Overridden to close paragraph
158: * @throws IOException for I/O problems
159: */
160: protected void writeRtfSuffix() throws IOException {
161: // sometimes the end of paragraph mark must be suppressed in table cells
162: boolean writeMark = true;
163: if (parent instanceof RtfTableCell) {
164: writeMark = ((RtfTableCell) parent).paragraphNeedsPar(this );
165: }
166: if (writeMark) {
167: writeControlWord("par");
168: }
169:
170: if (mustWriteGroupMark()) {
171: writeGroupMark(false);
172: }
173:
174: }
175:
176: /**
177: * Close current text run if any and start a new one with default attributes
178: * @param str if not null, added to the RtfText created
179: * @return the new RtfText object
180: * @throws IOException for I/O problems
181: */
182: public RtfText newText(String str) throws IOException {
183: return newText(str, null);
184: }
185:
186: /**
187: * Close current text run if any and start a new one
188: * @param str if not null, added to the RtfText created
189: * @param attr attributes of the text
190: * @return the new RtfText object
191: * @throws IOException for I/O problems
192: */
193: public RtfText newText(String str, RtfAttributes attr)
194: throws IOException {
195: closeAll();
196: text = new RtfText(this , writer, str, attr);
197: return text;
198: }
199:
200: /**
201: * add a page break
202: * @throws IOException for I/O problems
203: */
204: public void newPageBreak() throws IOException {
205: writeForBreak = true;
206: new RtfPageBreak(this , writer);
207: }
208:
209: /**
210: * add a line break
211: * @throws IOException for I/O problems
212: */
213: public void newLineBreak() throws IOException {
214: new RtfLineBreak(this , writer);
215: }
216:
217: /**
218: * Add a page number
219: * @return new RtfPageNumber object
220: * @throws IOException for I/O problems
221: */
222: public RtfPageNumber newPageNumber() throws IOException {
223: pageNumber = new RtfPageNumber(this , writer);
224: return pageNumber;
225: }
226:
227: /**
228: * Added by Boris POUDEROUS on 2002/07/09
229: * @param id string containing the citation text
230: * @return the new RtfPageNumberCitation object
231: * @throws IOException for I/O problems
232: */
233: public RtfPageNumberCitation newPageNumberCitation(String id)
234: throws IOException {
235: pageNumberCitation = new RtfPageNumberCitation(this , writer, id);
236: return pageNumberCitation;
237: }
238:
239: /**
240: * Creates a new hyperlink.
241: * @param str string containing the hyperlink text
242: * @param attr attributes of new hyperlink
243: * @return the new RtfHyperLink object
244: * @throws IOException for I/O problems
245: */
246: public RtfHyperLink newHyperLink(String str, RtfAttributes attr)
247: throws IOException {
248: hyperlink = new RtfHyperLink(this , writer, str, attr);
249: return hyperlink;
250: }
251:
252: /**
253: * Start a new external graphic after closing all other elements
254: * @return the new RtfExternalGraphic
255: * @throws IOException for I/O problems
256: */
257: public RtfExternalGraphic newImage() throws IOException {
258: closeAll();
259: externalGraphic = new RtfExternalGraphic(this , writer);
260: return externalGraphic;
261: }
262:
263: private void closeCurrentText() throws IOException {
264: if (text != null) {
265: text.close();
266: }
267: }
268:
269: private void closeCurrentHyperLink() throws IOException {
270: if (hyperlink != null) {
271: hyperlink.close();
272: }
273: }
274:
275: private void closeAll() throws IOException {
276: closeCurrentText();
277: closeCurrentHyperLink();
278: }
279:
280: /**
281: * Depending on RtfOptions, do not emit any RTF for empty paragraphs
282: * @return true if RTF should be written
283: */
284: protected boolean okToWriteRtf() {
285: boolean result = super .okToWriteRtf();
286:
287: if (parent.getOptions().ignoreEmptyParagraphs()
288: && getChildCount() == 0) {
289: // TODO should test that this is the last RtfParagraph in the cell instead
290: // of simply testing for last child??
291: result = false;
292: }
293:
294: return result;
295: }
296:
297: /** true if we must write our own (non-text) attributes in the RTF */
298: private boolean mustWriteAttributes() {
299: boolean writeAttributes = false;
300: final int children = getChildCount();
301: if (children > 0) {
302: final List childList = getChildren();
303: for (int i = 0; i < children; i++) {
304: final RtfElement el = (RtfElement) childList.get(i);
305: if (!el.isEmpty()) {
306: if (el.getClass() == RtfText.class) {
307: boolean tmp = ((RtfText) el).isNbsp();
308: if (!tmp) {
309: writeAttributes = true;
310: break;
311: }
312: } else {
313: writeAttributes = true;
314: break;
315: }
316: }
317: }
318: }
319: return writeAttributes;
320: }
321:
322: /** true if we must write a group mark around this paragraph
323: * TODO is this correct, study interaction with mustWriteAttributes()
324: * <-- On implementation i have noticed if the groupmark set, the
325: * format attributes are only for this content, i think this
326: * implementation is ok
327: */
328: private boolean mustWriteGroupMark() {
329: return getChildCount() > 0;
330: }
331:
332: /**
333: * accessor for text attributes
334: * @return attributes of the text
335: */
336: public RtfAttributes getTextAttributes() {
337: if (text == null) {
338: return null;
339: }
340: return text.getTextAttributes();
341: }
342: }
|