/* * 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 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; } RtfAttributes tableBorderAttributes = getTable().getBorderAttributes(); int index = 0; for (Object o : getChildren()) { final RtfElement e = (RtfElement) o; 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; } final Integer rightPadStr = (Integer)attrib.getValue(ATTR_ROW_PADDING_RIGHT); if (rightPadStr != null) { gaph = (gaph + rightPadStr) / 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; } }