blob: 8dd58739cd026881463c927c981beb6f70c50107 [file] [log] [blame]
/*
* 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;
/*
* This file is part of the RTF library of the FOP project, which was originally
* created by Bertrand Delacretaz <bdelacretaz@codeconsult.ch> and by other
* contributors to the jfor project (www.jfor.org), who agreed to donate jfor to
* the FOP project.
*/
import java.io.IOException;
import java.io.Writer;
import java.util.Iterator;
import org.apache.fop.apps.FOPException;
/**
* <p>Container for RtfTableCell elements.</p>
*
* <p>This work was authored by Bertrand Delacretaz (bdelacretaz@codeconsult.ch),
* Andreas Putz (a.putz@skynamics.com), and
* Roberto Marra (roberto@link-u.com).</p>
*/
public class RtfTableRow extends RtfContainer implements ITableAttributes {
private RtfTableCell cell;
// private RtfExtraRowSet extraRowSet;
private int id;
private int highestCell;
/** Create an RTF element as a child of given container */
RtfTableRow(RtfTable parent, Writer w, int idNum) throws IOException {
super(parent, w);
id = idNum;
}
/** Create an RTF element as a child of given container */
RtfTableRow(RtfTable parent, Writer w, RtfAttributes attrs, int idNum) throws IOException {
super(parent, w, attrs);
id = idNum;
}
/**
* Close current cell if any and start a new one
* @param cellWidth width of new cell
* @return new RtfTableCell
* @throws IOException for I/O problems
*/
public RtfTableCell newTableCell(int cellWidth) throws IOException {
highestCell++;
cell = new RtfTableCell(this, writer, cellWidth, highestCell);
return cell;
}
/**
* Close current cell if any and start a new one
* @param attrs attributes of new cell
* @param cellWidth width of new cell
* @return new RtfTableCell
* @throws IOException for I/O problems
*/
public RtfTableCell newTableCell(int cellWidth, RtfAttributes attrs) throws IOException {
highestCell++;
cell = new RtfTableCell(this, writer, cellWidth, attrs, highestCell);
return cell;
}
/**
* Added by Boris POUDEROUS on 07/02/2002
* in order to add an empty cell that is merged with the cell above.
* This cell is placed before or after the nested table.
* @param attrs attributes of new cell
* @param cellWidth width of new cell
* @return new RtfTableCell
* @throws IOException for I/O problems
*/
public RtfTableCell newTableCellMergedVertically(int cellWidth,
RtfAttributes attrs) throws IOException {
highestCell++;
cell = new RtfTableCell(this, writer, cellWidth, attrs, highestCell);
cell.setVMerge(RtfTableCell.MERGE_WITH_PREVIOUS);
return cell;
}
/**
* Added by Boris POUDEROUS on 07/02/2002
* in order to add an empty cell that is merged with the previous cell.
* @param attrs attributes of new cell
* @param cellWidth width of new cell
* @return new RtfTableCell
* @throws IOException for I/O problems
* @throws FOPException if attributes cannot be cloned
*/
public RtfTableCell newTableCellMergedHorizontally(int cellWidth,
RtfAttributes attrs) throws IOException, FOPException {
highestCell++;
// Added by Normand Masse
// Inherit attributes from base cell for merge
RtfAttributes wAttributes = null;
if (attrs != null) {
try {
wAttributes = (RtfAttributes)attrs.clone();
} catch (CloneNotSupportedException e) {
throw new FOPException(e);
}
}
cell = new RtfTableCell(this, writer, cellWidth, wAttributes, highestCell);
cell.setHMerge(RtfTableCell.MERGE_WITH_PREVIOUS);
return cell;
}
/**
* @throws IOException for I/O problems
*/
protected void writeRtfPrefix() throws IOException {
newLine();
writeGroupMark(true);
}
/**
* Overridden to write trowd and cell definitions before writing our cells
* @throws IOException for I/O problems
*/
protected void writeRtfContent() throws IOException {
if (getTable().isNestedTable()) {
//nested table
writeControlWord("intbl");
//itap is the depth (level) of the current nested table
writeControlWord("itap" + getTable().getNestedTableDepth());
} else {
//normal (not nested) table
writeRowAndCellsDefintions();
}
// now children can write themselves, we have the correct RTF prefix code
super.writeRtfContent();
}
/**
*
* @throws IOException In case of a IO-problem
*/
public void writeRowAndCellsDefintions() throws IOException {
// render the row and cells definitions
writeControlWord("trowd");
if (!getTable().isNestedTable()) {
writeControlWord("itap0");
}
//check for keep-together
if (attrib.isSet(ITableAttributes.ROW_KEEP_TOGETHER)) {
writeControlWord(ROW_KEEP_TOGETHER);
}
writePaddingAttributes();
final RtfTable parentTable = (RtfTable) parent;
adjustBorderProperties(parentTable);
writeAttributes(attrib, new String[]{ITableAttributes.ATTR_HEADER});
writeAttributes(attrib, ITableAttributes.ROW_BORDER);
writeAttributes(attrib, ITableAttributes.CELL_BORDER);
writeAttributes(attrib, IBorderAttributes.BORDERS);
if (attrib.isSet(ITableAttributes.ROW_HEIGHT)) {
writeOneAttribute(
ITableAttributes.ROW_HEIGHT,
attrib.getValue(ITableAttributes.ROW_HEIGHT));
}
// write X positions of our cells
int xPos = 0;
final Object leftIndent = attrib.getValue(ITableAttributes.ATTR_ROW_LEFT_INDENT);
if (leftIndent != null) {
xPos = ((Integer)leftIndent).intValue();
}
RtfAttributes tableBorderAttributes = getTable().getBorderAttributes();
int index = 0;
for (Iterator it = getChildren().iterator(); it.hasNext();) {
final RtfElement e = (RtfElement)it.next();
if (e instanceof RtfTableCell) {
RtfTableCell rtfcell = (RtfTableCell)e;
// Adjust the cell's display attributes so the table's/row's borders
// are drawn properly.
if (tableBorderAttributes != null) {
// get border attributes from table
if (index == 0) {
String border = ITableAttributes.CELL_BORDER_LEFT;
if (!rtfcell.getRtfAttributes().isSet(border)) {
rtfcell.getRtfAttributes().set(border,
(RtfAttributes) tableBorderAttributes.getValue(border));
}
}
if (index == this.getChildCount() - 1) {
String border = ITableAttributes.CELL_BORDER_RIGHT;
if (!rtfcell.getRtfAttributes().isSet(border)) {
rtfcell.getRtfAttributes().set(border,
(RtfAttributes) tableBorderAttributes.getValue(border));
}
}
if (isFirstRow()) {
String border = ITableAttributes.CELL_BORDER_TOP;
if (!rtfcell.getRtfAttributes().isSet(border)) {
rtfcell.getRtfAttributes().set(border,
(RtfAttributes) tableBorderAttributes.getValue(border));
}
}
if ((parentTable != null) && (parentTable.isHighestRow(id))) {
String border = ITableAttributes.CELL_BORDER_BOTTOM;
if (!rtfcell.getRtfAttributes().isSet(border)) {
rtfcell.getRtfAttributes().set(border,
(RtfAttributes) tableBorderAttributes.getValue(border));
}
}
}
// get border attributes from row
if (index == 0) {
if (!rtfcell.getRtfAttributes().isSet(ITableAttributes.CELL_BORDER_LEFT)) {
rtfcell.getRtfAttributes().set(ITableAttributes.CELL_BORDER_LEFT,
(String) attrib.getValue(ITableAttributes.ROW_BORDER_LEFT));
}
}
if (index == this.getChildCount() - 1) {
if (!rtfcell.getRtfAttributes().isSet(ITableAttributes.CELL_BORDER_RIGHT)) {
rtfcell.getRtfAttributes().set(ITableAttributes.CELL_BORDER_RIGHT,
(String) attrib.getValue(ITableAttributes.ROW_BORDER_RIGHT));
}
}
if (isFirstRow()) {
if (!rtfcell.getRtfAttributes().isSet(ITableAttributes.CELL_BORDER_TOP)) {
rtfcell.getRtfAttributes().set(ITableAttributes.CELL_BORDER_TOP,
(String) attrib.getValue(ITableAttributes.ROW_BORDER_TOP));
}
}
if ((parentTable != null) && (parentTable.isHighestRow(id))) {
if (!rtfcell.getRtfAttributes().isSet(ITableAttributes.CELL_BORDER_BOTTOM)) {
rtfcell.getRtfAttributes().set(ITableAttributes.CELL_BORDER_BOTTOM,
(String) attrib.getValue(ITableAttributes.ROW_BORDER_BOTTOM));
}
}
// write cell's definition
xPos = rtfcell.writeCellDef(xPos);
}
index++; // Added by Boris POUDEROUS on 2002/07/02
}
newLine();
}
private void adjustBorderProperties(RtfTable parentTable) {
// if we have attributes, manipulate border properties
if (attrib != null && parentTable != null) {
//if table is only one row long
if (isFirstRow() && parentTable.isHighestRow(id)) {
attrib.unset(ITableAttributes.ROW_BORDER_HORIZONTAL);
//or if row is the first row
} else if (isFirstRow()) {
attrib.unset(ITableAttributes.ROW_BORDER_BOTTOM);
//or if row is the last row
} else if (parentTable.isHighestRow(id)) {
attrib.unset(ITableAttributes.ROW_BORDER_TOP);
//else the row is an inside row
} else {
attrib.unset(ITableAttributes.ROW_BORDER_BOTTOM);
attrib.unset(ITableAttributes.ROW_BORDER_TOP);
}
}
}
/**
* Overridden to write RTF suffix code, what comes after our children
* @throws IOException for I/O problems
*/
protected void writeRtfSuffix() throws IOException {
if (getTable().isNestedTable()) {
//nested table
writeGroupMark(true);
writeStarControlWord("nesttableprops");
writeRowAndCellsDefintions();
writeControlWordNS("nestrow");
writeGroupMark(false);
writeGroupMark(true);
writeControlWord("nonesttables");
writeControlWord("par");
writeGroupMark(false);
} else {
writeControlWord("row");
}
writeGroupMark(false);
}
// RtfExtraRowSet getExtraRowSet() {
// return extraRowSet;
// }
private void writePaddingAttributes()
throws IOException {
// Row padding attributes generated in the converter package
// use RTF 1.6 definitions - try to compute a reasonable RTF 1.5 value
// out of them if present
// how to do vertical padding with RTF 1.5?
if (attrib != null && !attrib.isSet(ATTR_RTF_15_TRGAPH)) {
int gaph = -1;
try {
// set (RTF 1.5) gaph to the average of the (RTF 1.6) left and right padding values
final Integer leftPadStr = (Integer)attrib.getValue(ATTR_ROW_PADDING_LEFT);
if (leftPadStr != null) {
gaph = leftPadStr.intValue();
}
final Integer rightPadStr = (Integer)attrib.getValue(ATTR_ROW_PADDING_RIGHT);
if (rightPadStr != null) {
gaph = (gaph + rightPadStr.intValue()) / 2;
}
} catch (Exception e) {
final String msg = "RtfTableRow.writePaddingAttributes: " + e.toString();
// getRtfFile().getLog().logWarning(msg);
}
if (gaph >= 0) {
attrib.set(ATTR_RTF_15_TRGAPH, gaph);
}
}
// write all padding attributes
writeAttributes(attrib, ATTRIB_ROW_PADDING);
}
/**
* @return true if the row is the first in the table
*/
public boolean isFirstRow() {
return (id == 1);
}
/**
* @param cellId cell id to check
* @return true if the cell is the highest cell
*/
public boolean isHighestCell(int cellId) {
return (highestCell == cellId) ? true : false;
}
/**
*
* @return Parent table of the row.
*/
public RtfTable getTable() {
RtfElement e = this;
while (e.parent != null) {
if (e.parent instanceof RtfTable) {
return (RtfTable) e.parent;
}
e = e.parent;
}
return null;
}
}