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: RtfTableRow.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.IOException;
030: import java.io.Writer;
031: import java.util.Iterator;
032:
033: /** Container for RtfTableCell elements
034: * @author Bertrand Delacretaz bdelacretaz@codeconsult.ch
035: * @author Andreas Putz a.putz@skynamics.com
036: * @author Roberto Marra roberto@link-u.com
037: */
038:
039: public class RtfTableRow extends RtfContainer implements
040: ITableAttributes {
041: private RtfTableCell cell;
042: // private RtfExtraRowSet extraRowSet;
043: private int id;
044: private int highestCell = 0;
045:
046: /** Create an RTF element as a child of given container */
047: RtfTableRow(RtfTable parent, Writer w, int idNum)
048: throws IOException {
049: super (parent, w);
050: id = idNum;
051: }
052:
053: /** Create an RTF element as a child of given container */
054: RtfTableRow(RtfTable parent, Writer w, RtfAttributes attrs,
055: int idNum) throws IOException {
056: super (parent, w, attrs);
057: id = idNum;
058: }
059:
060: /**
061: * Close current cell if any and start a new one
062: * @param cellWidth width of new cell
063: * @return new RtfTableCell
064: * @throws IOException for I/O problems
065: */
066: public RtfTableCell newTableCell(int cellWidth) throws IOException {
067: highestCell++;
068: cell = new RtfTableCell(this , writer, cellWidth, highestCell);
069: return cell;
070: }
071:
072: /**
073: * Close current cell if any and start a new one
074: * @param attrs attributes of new cell
075: * @param cellWidth width of new cell
076: * @return new RtfTableCell
077: * @throws IOException for I/O problems
078: */
079: public RtfTableCell newTableCell(int cellWidth, RtfAttributes attrs)
080: throws IOException {
081: highestCell++;
082: cell = new RtfTableCell(this , writer, cellWidth, attrs,
083: highestCell);
084: return cell;
085: }
086:
087: /**
088: * Added by Boris POUDEROUS on 07/02/2002
089: * in order to add an empty cell that is merged with the cell above.
090: * This cell is placed before or after the nested table.
091: * @param attrs attributes of new cell
092: * @param cellWidth width of new cell
093: * @return new RtfTableCell
094: * @throws IOException for I/O problems
095: */
096: public RtfTableCell newTableCellMergedVertically(int cellWidth,
097: RtfAttributes attrs) throws IOException {
098: highestCell++;
099: cell = new RtfTableCell(this , writer, cellWidth, attrs,
100: highestCell);
101: cell.setVMerge(RtfTableCell.MERGE_WITH_PREVIOUS);
102: return cell;
103: }
104:
105: /**
106: * Added by Boris POUDEROUS on 07/02/2002
107: * in order to add an empty cell that is merged with the previous cell.
108: * @param attrs attributes of new cell
109: * @param cellWidth width of new cell
110: * @return new RtfTableCell
111: * @throws IOException for I/O problems
112: */
113: public RtfTableCell newTableCellMergedHorizontally(int cellWidth,
114: RtfAttributes attrs) throws IOException {
115: highestCell++;
116: // Added by Normand Masse
117: // Inherit attributes from base cell for merge
118: RtfAttributes wAttributes = null;
119: if (attrs != null) {
120: wAttributes = (RtfAttributes) attrs.clone();
121: }
122:
123: cell = new RtfTableCell(this , writer, cellWidth, wAttributes,
124: highestCell);
125: cell.setHMerge(RtfTableCell.MERGE_WITH_PREVIOUS);
126: return cell;
127: }
128:
129: /**
130: * @throws IOException for I/O problems
131: */
132: protected void writeRtfPrefix() throws IOException {
133: newLine();
134: writeGroupMark(true);
135: }
136:
137: /**
138: * Overridden to write trowd and cell definitions before writing our cells
139: * @throws IOException for I/O problems
140: */
141: protected void writeRtfContent() throws IOException {
142:
143: if (getTable().isNestedTable()) {
144: //nested table
145: writeControlWord("intbl");
146: writeControlWord("itap2");
147: } else {
148: //normal (not nested) table
149: writeRowAndCellsDefintions();
150: }
151: // now children can write themselves, we have the correct RTF prefix code
152: super .writeRtfContent();
153: }
154:
155: /**
156: *
157: * @throws IOException In case of a IO-problem
158: */
159: public void writeRowAndCellsDefintions() throws IOException {
160: // render the row and cells definitions
161: writeControlWord("trowd");
162:
163: if (!getTable().isNestedTable()) {
164: writeControlWord("itap0");
165: }
166:
167: //check for keep-together
168: if (attrib != null
169: && attrib.isSet(ITableAttributes.ROW_KEEP_TOGETHER)) {
170: writeControlWord(ROW_KEEP_TOGETHER);
171: }
172:
173: writePaddingAttributes();
174:
175: final RtfTable parentTable = (RtfTable) parent;
176: adjustBorderProperties(parentTable);
177:
178: writeAttributes(attrib,
179: new String[] { ITableAttributes.ATTR_HEADER });
180: writeAttributes(attrib, ITableAttributes.ROW_BORDER);
181: writeAttributes(attrib, ITableAttributes.CELL_BORDER);
182: writeAttributes(attrib, IBorderAttributes.BORDERS);
183:
184: if (attrib.isSet(ITableAttributes.ROW_HEIGHT)) {
185: writeOneAttribute(ITableAttributes.ROW_HEIGHT, attrib
186: .getValue(ITableAttributes.ROW_HEIGHT));
187: }
188:
189: // write X positions of our cells
190: int xPos = 0;
191:
192: final Object leftIndent = attrib
193: .getValue(ITableAttributes.ATTR_ROW_LEFT_INDENT);
194: if (leftIndent != null) {
195: xPos = ((Integer) leftIndent).intValue();
196: }
197:
198: RtfAttributes tableBorderAttributes = getTable()
199: .getBorderAttributes();
200:
201: int index = 0;
202: for (Iterator it = getChildren().iterator(); it.hasNext();) {
203: final RtfElement e = (RtfElement) it.next();
204: if (e instanceof RtfTableCell) {
205:
206: RtfTableCell rtfcell = (RtfTableCell) e;
207:
208: // Adjust the cell's display attributes so the table's/row's borders
209: // are drawn properly.
210:
211: if (tableBorderAttributes != null) {
212: // get border attributes from table
213: if (index == 0) {
214: String border = ITableAttributes.CELL_BORDER_LEFT;
215: if (!rtfcell.getRtfAttributes().isSet(border)) {
216: rtfcell
217: .getRtfAttributes()
218: .set(
219: border,
220: (RtfAttributes) tableBorderAttributes
221: .getValue(border));
222: }
223: }
224:
225: if (index == this .getChildCount() - 1) {
226: String border = ITableAttributes.CELL_BORDER_RIGHT;
227: if (!rtfcell.getRtfAttributes().isSet(border)) {
228: rtfcell
229: .getRtfAttributes()
230: .set(
231: border,
232: (RtfAttributes) tableBorderAttributes
233: .getValue(border));
234: }
235: }
236:
237: if (isFirstRow()) {
238: String border = ITableAttributes.CELL_BORDER_TOP;
239: if (!rtfcell.getRtfAttributes().isSet(border)) {
240: rtfcell
241: .getRtfAttributes()
242: .set(
243: border,
244: (RtfAttributes) tableBorderAttributes
245: .getValue(border));
246: }
247: }
248:
249: if ((parentTable != null)
250: && (parentTable.isHighestRow(id))) {
251: String border = ITableAttributes.CELL_BORDER_BOTTOM;
252: if (!rtfcell.getRtfAttributes().isSet(border)) {
253: rtfcell
254: .getRtfAttributes()
255: .set(
256: border,
257: (RtfAttributes) tableBorderAttributes
258: .getValue(border));
259: }
260: }
261: }
262:
263: // get border attributes from row
264: if (index == 0) {
265: if (!rtfcell.getRtfAttributes().isSet(
266: ITableAttributes.CELL_BORDER_LEFT)) {
267: rtfcell
268: .getRtfAttributes()
269: .set(
270: ITableAttributes.CELL_BORDER_LEFT,
271: (String) attrib
272: .getValue(ITableAttributes.ROW_BORDER_LEFT));
273: }
274: }
275:
276: if (index == this .getChildCount() - 1) {
277: if (!rtfcell.getRtfAttributes().isSet(
278: ITableAttributes.CELL_BORDER_RIGHT)) {
279: rtfcell
280: .getRtfAttributes()
281: .set(
282: ITableAttributes.CELL_BORDER_RIGHT,
283: (String) attrib
284: .getValue(ITableAttributes.ROW_BORDER_RIGHT));
285: }
286: }
287:
288: if (isFirstRow()) {
289: if (!rtfcell.getRtfAttributes().isSet(
290: ITableAttributes.CELL_BORDER_TOP)) {
291: rtfcell
292: .getRtfAttributes()
293: .set(
294: ITableAttributes.CELL_BORDER_TOP,
295: (String) attrib
296: .getValue(ITableAttributes.ROW_BORDER_TOP));
297: }
298: }
299:
300: if ((parentTable != null)
301: && (parentTable.isHighestRow(id))) {
302: if (!rtfcell.getRtfAttributes().isSet(
303: ITableAttributes.CELL_BORDER_BOTTOM)) {
304: rtfcell
305: .getRtfAttributes()
306: .set(
307: ITableAttributes.CELL_BORDER_BOTTOM,
308: (String) attrib
309: .getValue(ITableAttributes.ROW_BORDER_BOTTOM));
310: }
311: }
312:
313: // write cell's definition
314: xPos = rtfcell.writeCellDef(xPos);
315: }
316: index++; // Added by Boris POUDEROUS on 2002/07/02
317: }
318:
319: newLine();
320: }
321:
322: private void adjustBorderProperties(RtfTable parentTable) {
323: // if we have attributes, manipulate border properties
324: if (attrib != null && parentTable != null) {
325:
326: //if table is only one row long
327: if (isFirstRow() && parentTable.isHighestRow(id)) {
328: attrib.unset(ITableAttributes.ROW_BORDER_HORIZONTAL);
329: //or if row is the first row
330: } else if (isFirstRow()) {
331: attrib.unset(ITableAttributes.ROW_BORDER_BOTTOM);
332: //or if row is the last row
333: } else if (parentTable.isHighestRow(id)) {
334: attrib.unset(ITableAttributes.ROW_BORDER_TOP);
335: //else the row is an inside row
336: } else {
337: attrib.unset(ITableAttributes.ROW_BORDER_BOTTOM);
338: attrib.unset(ITableAttributes.ROW_BORDER_TOP);
339: }
340: }
341: }
342:
343: /**
344: * Overridden to write RTF suffix code, what comes after our children
345: * @throws IOException for I/O problems
346: */
347: protected void writeRtfSuffix() throws IOException {
348: if (getTable().isNestedTable()) {
349: //nested table
350: writeGroupMark(true);
351: writeStarControlWord("nesttableprops");
352: writeRowAndCellsDefintions();
353: writeControlWordNS("nestrow");
354: writeGroupMark(false);
355:
356: writeGroupMark(true);
357: writeControlWord("nonesttables");
358: writeControlWord("par");
359: writeGroupMark(false);
360: } else {
361: writeControlWord("row");
362: }
363:
364: writeGroupMark(false);
365: }
366:
367: // RtfExtraRowSet getExtraRowSet() {
368: // return extraRowSet;
369: // }
370:
371: private void writePaddingAttributes() throws IOException {
372: // Row padding attributes generated in the converter package
373: // use RTF 1.6 definitions - try to compute a reasonable RTF 1.5 value
374: // out of them if present
375: // how to do vertical padding with RTF 1.5?
376: if (attrib != null && !attrib.isSet(ATTR_RTF_15_TRGAPH)) {
377: int gaph = -1;
378: try {
379: // set (RTF 1.5) gaph to the average of the (RTF 1.6) left and right padding values
380: final Integer leftPadStr = (Integer) attrib
381: .getValue(ATTR_ROW_PADDING_LEFT);
382: if (leftPadStr != null) {
383: gaph = leftPadStr.intValue();
384: }
385: final Integer rightPadStr = (Integer) attrib
386: .getValue(ATTR_ROW_PADDING_RIGHT);
387: if (rightPadStr != null) {
388: gaph = (gaph + rightPadStr.intValue()) / 2;
389: }
390: } catch (Exception e) {
391: final String msg = "RtfTableRow.writePaddingAttributes: "
392: + e.toString();
393: // getRtfFile().getLog().logWarning(msg);
394: }
395: if (gaph >= 0) {
396: attrib.set(ATTR_RTF_15_TRGAPH, gaph);
397: }
398: }
399:
400: // write all padding attributes
401: writeAttributes(attrib, ATTRIB_ROW_PADDING);
402: }
403:
404: /**
405: * @return true if the row is the first in the table
406: */
407: public boolean isFirstRow() {
408: return (id == 1);
409: }
410:
411: /**
412: * @param cellId cell id to check
413: * @return true if the cell is the highest cell
414: */
415: public boolean isHighestCell(int cellId) {
416: return (highestCell == cellId) ? true : false;
417: }
418:
419: /**
420: *
421: * @return Parent table of the row.
422: */
423: public RtfTable getTable() {
424: RtfElement e = this ;
425: while (e.parent != null) {
426: if (e.parent instanceof RtfTable) {
427: return (RtfTable) e.parent;
428: }
429:
430: e = e.parent;
431: }
432:
433: return null;
434: }
435: }
|