KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > render > rtf > rtflib > rtfdoc > RtfExtraRowSet


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 /* $Id: RtfExtraRowSet.java 426576 2006-07-28 15:44:37Z jeremias $ */
19
20 package org.apache.fop.render.rtf.rtflib.rtfdoc;
21
22 /*
23  * This file is part of the RTF library of the FOP project, which was originally
24  * created by Bertrand Delacretaz <bdelacretaz@codeconsult.ch> and by other
25  * contributors to the jfor project (www.jfor.org), who agreed to donate jfor to
26  * the FOP project.
27  */

28
29 import java.io.Writer JavaDoc;
30 import java.io.IOException JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.LinkedList JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.Collections JavaDoc;
35
36
37 /**
38  * Used to add extra table rows after a row that contains a nested table:
39  * <li> created by RtfTableRow before generating RTF code
40  * <li> an RtfTableCell that contains a nested table can ask this to put
41  * some of its children in extra rows that after the current row
42  * <li> once RtfTableRow is done rendering its children, it renders this,
43  * causing extra rows to be generated, with content that can come
44  * from several RtfTableCells
45  *
46  * See org.apache.fop.rtf.rtflib.testdocs.NestedTable for an example of
47  * usage.
48  * @author Bertrand Delacretaz bdelacretaz@codeconsult.ch
49  */

50
51 public class RtfExtraRowSet extends RtfContainer {
52     // TODO what is idnum?
53
static final int DEFAULT_IDNUM = 0;
54
55     /** Parent table context
56      * (added by Boris Poudérous on july 2002 in order to process nested tables)
57      */

58     private ITableColumnsInfo parentITableColumnsInfo = null;
59
60     /** While a top-level RtfTableRow is being rendered, we build a list of
61      * RtfTableCells that must be rendered in extra rows.
62      * This holds a cell with positioning information
63      */

64     private final List JavaDoc cells = new LinkedList JavaDoc();
65     private static class PositionedCell
66     implements Comparable JavaDoc {
67         private final RtfTableCell cell;
68         private final int xOffset;
69         private final int rowIndex;
70
71         PositionedCell(RtfTableCell c, int index, int offset) {
72             cell = c;
73             xOffset = offset;
74             rowIndex = index;
75         }
76
77         /** debugging dump */
78         public String JavaDoc toString() {
79             return "PositionedCell: row " + rowIndex + ", offset " + xOffset;
80         }
81
82         /** cells need to be sorted by row index and then by x offset */
83         public int compareTo(Object JavaDoc o) {
84             int result = 0;
85             if (o == null) {
86                 result = 1;
87             } else if (!(o instanceof PositionedCell)) {
88                 result = 1;
89             } else {
90                 final PositionedCell pc = (PositionedCell)o;
91                 if (this.rowIndex < pc.rowIndex) {
92                     result = -1;
93                 } else if (this.rowIndex > pc.rowIndex) {
94                     result = 1;
95                 } else if (this.xOffset < pc.xOffset) {
96                     result = -1;
97                 } else if (this.xOffset > pc.xOffset) {
98                     result = 1;
99                 }
100             }
101
102             return result;
103         }
104
105         public boolean equals(Object JavaDoc o) {
106             return o != null && this.compareTo(o) == 0;
107         }
108     }
109
110     /** our maximum row index */
111     private int maxRowIndex;
112
113     /** an RtfExtraRowSet has no parent, it is only used temporary during
114      * generation of RTF for an RtfTableRow
115      */

116     RtfExtraRowSet(Writer JavaDoc w)
117     throws IOException JavaDoc {
118         super(null, w);
119     }
120
121     /** Add all cells of given Table to this set for later rendering in extra rows
122      * @return index of extra row to use for elements that follow this table in the same cell
123      * @param rowIndex index of first extra row to create to hold cells of tbl
124      * @param xOffset horizontal position of left edge of first column of tbl
125      */

126     int addTable(RtfTable tbl, int rowIndex, int xOffset) {
127         // process all rows of the table
128
for (Iterator JavaDoc it = tbl.getChildren().iterator(); it.hasNext();) {
129             final RtfElement e = (RtfElement)it.next();
130             if (e instanceof RtfTableRow) {
131                 addRow((RtfTableRow)e, rowIndex, xOffset);
132                 rowIndex++;
133                 maxRowIndex = Math.max(rowIndex, maxRowIndex);
134             }
135         }
136         return rowIndex;
137     }
138
139     /** add all cells of given row to this set */
140     private void addRow(RtfTableRow row, int rowIndex, int xOffset) {
141         for (Iterator JavaDoc it = row.getChildren().iterator(); it.hasNext();) {
142             final RtfElement e = (RtfElement)it.next();
143             if (e instanceof RtfTableCell) {
144                 final RtfTableCell c = (RtfTableCell)e;
145                 cells.add(new PositionedCell(c, rowIndex, xOffset));
146                 xOffset += c.getCellWidth();
147             }
148         }
149     }
150
151     /** create an extra cell to hold content that comes after a nested table in a cell
152      * Modified by Boris Poudérous in order to permit the extra cell to have
153      * the attributes of its parent cell
154      */

155     RtfTableCell createExtraCell(int rowIndex, int xOffset, int cellWidth,
156                                  RtfAttributes parentCellAttributes)
157     throws IOException JavaDoc {
158         final RtfTableCell c = new RtfTableCell(null, writer, cellWidth,
159                 parentCellAttributes, DEFAULT_IDNUM);
160         cells.add(new PositionedCell(c, rowIndex, xOffset));
161         return c;
162     }
163
164     /**
165      * render extra RtfTableRows containing all the extra RtfTableCells that we
166      * contain
167      * @throws IOException for I/O problems
168      */

169     protected void writeRtfContent() throws IOException JavaDoc {
170         // sort cells by rowIndex and xOffset
171
Collections.sort(cells);
172
173         // process all extra cells by rendering them into extra rows
174
List JavaDoc rowCells = null;
175         int rowIndex = -1;
176         for (Iterator JavaDoc it = cells.iterator(); it.hasNext();) {
177             final PositionedCell pc = (PositionedCell)it.next();
178             if (pc.rowIndex != rowIndex) {
179                 // starting a new row, render previous one
180
if (rowCells != null) {
181                     writeRow(rowCells);
182                 }
183                 rowIndex = pc.rowIndex;
184                 rowCells = new LinkedList JavaDoc();
185             }
186             rowCells.add(pc);
187         }
188
189         // render last row
190
if (rowCells != null) {
191             writeRow(rowCells);
192         }
193     }
194
195     /** write one RtfTableRow containing given PositionedCells */
196     private void writeRow(List JavaDoc cells)
197     throws IOException JavaDoc {
198         if (allCellsEmpty(cells)) {
199             return;
200         }
201
202         final RtfTableRow row = new RtfTableRow(null, writer, DEFAULT_IDNUM);
203         int cellIndex = 0;
204
205         // Get the context of the table that holds the nested table
206
ITableColumnsInfo parentITableColumnsInfo = getParentITableColumnsInfo();
207         parentITableColumnsInfo.selectFirstColumn();
208
209         // X offset of the current empty cell to add
210
float xOffset = 0;
211         float xOffsetOfLastPositionedCell = 0;
212
213         for (Iterator JavaDoc it = cells.iterator(); it.hasNext();) {
214             final PositionedCell pc = (PositionedCell)it.next();
215
216             // if first cell is not at offset 0, add placeholder cell
217
// TODO should be merged with the cell that is above it
218
if (cellIndex == 0 && pc.xOffset > 0) {
219                /**
220                 * Added by Boris Poudérous
221                 */

222                // Add empty cells merged vertically with the cells above and with the same widths
223
// (BEFORE the cell that contains the nested table)
224
for (int i = 0; (xOffset < pc.xOffset)
225                         && (i < parentITableColumnsInfo.getNumberOfColumns()); i++) {
226                     // Get the width of the cell above
227
xOffset += parentITableColumnsInfo.getColumnWidth();
228                     // Create the empty cell merged vertically
229
row.newTableCellMergedVertically((int)parentITableColumnsInfo.getColumnWidth(),
230                            pc.cell.attrib);
231                     // Select next column in order to have its width
232
parentITableColumnsInfo.selectNextColumn();
233                 }
234             }
235
236             row.addChild(pc.cell);
237             // Line added by Boris Poudérous
238
xOffsetOfLastPositionedCell = pc.xOffset + pc.cell.getCellWidth();
239             cellIndex++;
240         }
241
242         /**
243          * Added by Boris Poudérous
244          */

245         // Add empty cells merged vertically with the cells above AFTER the cell
246
// that contains the nested table
247
// The cells added have the same widths than the cells above.
248
if (parentITableColumnsInfo.getColumnIndex()
249                 < (parentITableColumnsInfo.getNumberOfColumns() - 1)) {
250             parentITableColumnsInfo.selectNextColumn();
251
252             while (parentITableColumnsInfo.getColumnIndex()
253                    < parentITableColumnsInfo.getNumberOfColumns()) {
254                   // Create the empty cell merged vertically
255
// TODO : the new cells after the extra cell don't have its
256
// attributes as we did for the previous cells.
257
// => in fact the m_attrib below (last argument) is
258
// empty => should be the attributes of the above cells.
259
row.newTableCellMergedVertically((int)parentITableColumnsInfo.getColumnWidth(),
260                           attrib);
261                   // Select next column in order to have its width
262
parentITableColumnsInfo.selectNextColumn();
263                 }
264            }
265
266         row.writeRtf();
267     }
268
269     /** true if all cells of given list are empty
270      * @param cells List of PositionedCell objects
271      */

272     private static boolean allCellsEmpty(List JavaDoc cells) {
273         boolean empty = true;
274         for (Iterator JavaDoc it = cells.iterator(); it.hasNext();) {
275             final PositionedCell pc = (PositionedCell)it.next();
276             if (pc.cell.containsText()) {
277                 empty = false;
278                 break;
279             }
280         }
281         return empty;
282     }
283
284     /**
285      * As this contains cells from several rows, we say that it's empty
286      * only if we have no cells.
287      * writeRow makes the decision about rendering specific rows
288      * @return false (always)
289      */

290     public boolean isEmpty() {
291         return false;
292     }
293
294     /**
295      * @return The table context of the parent table
296      * Added by Boris Poudérous on july 2002 in order to process nested tables
297      */

298      public ITableColumnsInfo getParentITableColumnsInfo() {
299        return this.parentITableColumnsInfo;
300      }
301
302      /**
303       *
304       * @param parentITableColumnsInfo table context to set
305       */

306      public void setParentITableColumnsInfo (ITableColumnsInfo parentITableColumnsInfo) {
307        this.parentITableColumnsInfo = parentITableColumnsInfo;
308      }
309      /** - end - */
310 }
311
Popular Tags