KickJava   Java API By Example, From Geeks To Geeks.

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


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: RtfTableCell.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.Iterator JavaDoc;
32
33 /** A cell in an RTF table, container for paragraphs, lists, etc.
34  * @author Bertrand Delacretaz bdelacretaz@codeconsult.ch
35  */

36
37 public class RtfTableCell
38         extends RtfContainer
39         implements IRtfParagraphContainer, IRtfListContainer, IRtfTableContainer,
40             IRtfExternalGraphicContainer, IRtfTextrunContainer {
41     private RtfParagraph paragraph;
42     private RtfList list;
43     private RtfTable table;
44     private RtfExternalGraphic externalGraphic;
45     private final RtfTableRow parentRow;
46     private boolean setCenter;
47     private boolean setRight;
48     private int id;
49
50     /** default cell width (in twips ??) */
51     public static final int DEFAULT_CELL_WIDTH = 2000;
52
53     /** cell width in twips */
54     private int cellWidth;
55     private int widthOffset;
56
57     /** cell merging has three states */
58     private int vMerge = NO_MERGE;
59     private int hMerge = NO_MERGE;
60
61     /** cell merging: this cell is not merged */
62     public static final int NO_MERGE = 0;
63
64     /** cell merging: this cell is the start of a range of merged cells */
65     public static final int MERGE_START = 1;
66
67     /** cell merging: this cell is part of (but not the start of) a range of merged cells */
68     public static final int MERGE_WITH_PREVIOUS = 2;
69
70     /** Create an RTF element as a child of given container */
71     RtfTableCell(RtfTableRow parent, Writer JavaDoc w, int cellWidth, int idNum) throws IOException JavaDoc {
72         super(parent, w);
73         id = idNum;
74         parentRow = parent;
75         this.cellWidth = cellWidth;
76         setCenter = false;
77         setRight = false;
78
79     }
80
81     /** Create an RTF element as a child of given container */
82     RtfTableCell(RtfTableRow parent, Writer JavaDoc w, int cellWidth, RtfAttributes attrs,
83             int idNum) throws IOException JavaDoc {
84         super(parent, w, attrs);
85         id = idNum;
86         parentRow = parent;
87         this.cellWidth = cellWidth;
88     }
89
90     /**
91      * Start a new paragraph after closing current current paragraph, list and table
92      * @param attrs attributes of new RtfParagraph
93      * @return new RtfParagraph object
94      * @throws IOException for I/O problems
95      */

96     public RtfParagraph newParagraph(RtfAttributes attrs) throws IOException JavaDoc {
97         closeAll();
98
99         // in tables, RtfParagraph must have the intbl attribute
100
if (attrs == null) {
101             attrs = new RtfAttributes();
102         }
103         
104         attrs.set("intbl");
105
106         paragraph = new RtfParagraph(this, writer, attrs);
107
108         if (paragraph.attrib.isSet("qc")) {
109             setCenter = true;
110             attrs.set("qc");
111         } else if (paragraph.attrib.isSet("qr")) {
112             setRight = true;
113             attrs.set("qr");
114         } else {
115             attrs.set("ql");
116         }
117         attrs.set("intbl");
118
119
120         //lines modified by Chris Scott, Westinghouse
121
return paragraph;
122     }
123
124     /**
125      * Start a new external graphic after closing current paragraph, list and table
126      * @throws IOException for I/O problems
127      * @return new RtfExternalGraphic object
128      */

129     public RtfExternalGraphic newImage() throws IOException JavaDoc {
130         closeAll();
131         externalGraphic = new RtfExternalGraphic(this, writer);
132         return externalGraphic;
133     }
134
135     /**
136      * Start a new paragraph with default attributes after closing current
137      * paragraph, list and table
138      * @return new RtfParagraph object
139      * @throws IOException for I/O problems
140      */

141     public RtfParagraph newParagraph() throws IOException JavaDoc {
142         return newParagraph(null);
143     }
144
145     /**
146      * Start a new list after closing current paragraph, list and table
147      * @param attrib attributes for new RtfList
148      * @return new RtfList object
149      * @throws IOException for I/O problems
150      */

151     public RtfList newList(RtfAttributes attrib) throws IOException JavaDoc {
152         closeAll();
153         list = new RtfList(this, writer, attrib);
154         return list;
155     }
156
157     /**
158      * Start a new nested table after closing current paragraph, list and table
159      * @param tc table column info for new RtfTable
160      * @return new RtfTable object
161      * @throws IOException for I/O problems
162      */

163     public RtfTable newTable(ITableColumnsInfo tc) throws IOException JavaDoc {
164         closeAll();
165         table = new RtfTable(this, writer, tc);
166         return table;
167     }
168
169     /**
170      * Start a new nested table after closing current paragraph, list and table
171      * @param attrs attributes of new RtfTable
172      * @param tc table column info for new RtfTable
173      * @return new RtfTable object
174      * @throws IOException for I/O problems
175      */

176     // Modified by Boris Poudérous on 07/22/2002
177
public RtfTable newTable(RtfAttributes attrs, ITableColumnsInfo tc) throws IOException JavaDoc {
178         closeAll();
179         table = new RtfTable(this, writer, attrs, tc); // Added tc Boris Poudérous 07/22/2002
180
return table;
181     }
182
183     /** used by RtfTableRow to write the <celldef> cell definition control words
184      * @param widthOffset sum of the widths of preceeding cells in same row
185      * @return widthOffset + width of this cell
186      */

187     int writeCellDef(int offset) throws IOException JavaDoc {
188         /*
189          * Don't write \clmgf or \clmrg. Instead add the widths
190          * of all spanned columns and create a single wider cell,
191          * because \clmgf and \clmrg won't work in last row of a
192          * table (Word2000 seems to do the same).
193          * Cause of this, dont't write horizontally merged cells.
194          * They just exist as placeholders in TableContext class,
195          * and are never written to RTF file.
196          */

197         // horizontal cell merge codes
198
if (hMerge == MERGE_WITH_PREVIOUS) {
199             return offset;
200         }
201         
202         newLine();
203         this.widthOffset = offset;
204
205         // vertical cell merge codes
206
if (vMerge == MERGE_START) {
207             writeControlWord("clvmgf");
208         } else if (vMerge == MERGE_WITH_PREVIOUS) {
209             writeControlWord("clvmrg");
210         }
211
212         /**
213          * Added by Boris POUDEROUS on 2002/06/26
214          */

215         // Cell background color processing :
216
writeAttributes (attrib, ITableAttributes.CELL_COLOR);
217         /** - end - */
218
219         writeAttributes (attrib, ITableAttributes.ATTRIB_CELL_PADDING);
220         writeAttributes (attrib, ITableAttributes.CELL_BORDER);
221         writeAttributes (attrib, IBorderAttributes.BORDERS);
222
223         // determine cell width
224
int iCurrentWidth = this.cellWidth;
225         if (attrib.getValue("number-columns-spanned") != null) {
226             // Get the number of columns spanned
227
int nbMergedCells = ((Integer JavaDoc)attrib.getValue("number-columns-spanned")).intValue();
228             
229             RtfTable tab = getRow().getTable();
230             
231             // Get the context of the current table in order to get the width of each column
232
ITableColumnsInfo tableColumnsInfo
233                 = tab.getITableColumnsInfo();
234             
235             tableColumnsInfo.selectFirstColumn();
236
237             // Reach the column index in table context corresponding to the current column cell
238
// id is the index of the current cell (it begins at 1)
239
// getColumnIndex() is the index of the current column in table context (it begins at 0)
240
// => so we must widthdraw 1 when comparing these two variables.
241
while ((this.id - 1) != tableColumnsInfo.getColumnIndex()) {
242                tableColumnsInfo.selectNextColumn();
243             }
244
245             // We widthdraw one cell because the first cell is already created
246
// (it's the current cell) !
247
int i = nbMergedCells - 1;
248             while (i > 0) {
249                 tableColumnsInfo.selectNextColumn();
250                 iCurrentWidth += (int)tableColumnsInfo.getColumnWidth();
251
252                 i--;
253             }
254         }
255         final int xPos = offset + iCurrentWidth;
256
257         //these lines added by Chris Scott, Westinghouse
258
//some attributes need to be writting before opening block
259
if (setCenter) {
260             writeControlWord("qc");
261         } else if (setRight) {
262             writeControlWord("qr");
263         } else {
264             writeControlWord("ql");
265         }
266
267         writeControlWord("cellx" + xPos);
268
269         //TODO Why is this here, right after an alignment command is written (see above)?
270
writeControlWord("ql");
271
272         return xPos;
273
274     }
275     
276     /**
277      * Overriden to avoid writing any it's a merged cell.
278      * @throws IOException for I/O problems
279      */

280     protected void writeRtfContent() throws IOException JavaDoc {
281        // Never write horizontally merged cells.
282
if (hMerge == MERGE_WITH_PREVIOUS) {
283            return;
284        }
285        
286        super.writeRtfContent();
287     }
288
289     /**
290      * Called before writeRtfContent; overriden to avoid writing
291      * any it's a merged cell.
292      * @throws IOException for I/O problems
293      */

294     protected void writeRtfPrefix() throws IOException JavaDoc {
295         // Never write horizontally merged cells.
296
if (hMerge == MERGE_WITH_PREVIOUS) {
297             return;
298         }
299         
300         super.writeRtfPrefix();
301     }
302
303     /**
304      * The "cell" control word marks the end of a cell
305      * @throws IOException for I/O problems
306      */

307     protected void writeRtfSuffix() throws IOException JavaDoc {
308         // Never write horizontally merged cells.
309
if (hMerge == MERGE_WITH_PREVIOUS) {
310             return;
311         }
312         
313         if (getRow().getTable().isNestedTable()) {
314             //nested table
315
writeControlWordNS("nestcell");
316             writeGroupMark(true);
317             writeControlWord("nonesttables");
318             writeControlWord("par");
319             writeGroupMark(false);
320         } else {
321             // word97 hangs if cell does not contain at least one "par" control word
322
// TODO this is what causes the extra spaces in nested table of test
323
// 004-spacing-in-tables.fo,
324
// but if is not here we generate invalid RTF for word97
325

326             if (setCenter) {
327                 writeControlWord("qc");
328             } else if (setRight) {
329                 writeControlWord("qr");
330             } else {
331                 RtfElement lastChild = null;
332                 
333                 if (getChildren().size() > 0) {
334                     lastChild = (RtfElement) getChildren().get(getChildren().size() - 1);
335                 }
336                     
337                 
338                 if (lastChild != null
339                         && lastChild instanceof RtfTextrun) {
340                     //Don't write \ql in order to allow for example a right aligned paragraph
341
//in a not right aligned table-cell to write its \qr.
342
} else {
343                     writeControlWord("ql");
344                 }
345             }
346
347             if (!containsText()) {
348                 writeControlWord("intbl");
349
350                 //R.Marra this create useless paragraph
351
//Seem working into Word97 with the "intbl" only
352
//writeControlWord("par");
353
}
354
355             writeControlWord("cell");
356         }
357     }
358
359
360     //modified by Chris Scott, Westinghouse
361
private void closeCurrentParagraph() throws IOException JavaDoc {
362         if (paragraph != null) {
363             paragraph.close();
364         }
365     }
366
367     private void closeCurrentList() throws IOException JavaDoc {
368         if (list != null) {
369             list.close();
370         }
371     }
372
373     private void closeCurrentTable() throws IOException JavaDoc {
374         if (table != null) {
375             table.close();
376         }
377     }
378
379     private void closeCurrentExternalGraphic() throws IOException JavaDoc {
380         if (externalGraphic != null) {
381             externalGraphic.close();
382         }
383     }
384
385     private void closeAll()
386     throws IOException JavaDoc {
387         closeCurrentTable();
388         closeCurrentParagraph();
389         closeCurrentList();
390         closeCurrentExternalGraphic();
391     }
392
393     /**
394      * @param mergeStatus vertical cell merging status to set
395      */

396     public void setVMerge(int mergeStatus) { this.vMerge = mergeStatus; }
397
398     /**
399      * @return vertical cell merging status
400      */

401     public int getVMerge() { return this.vMerge; }
402
403     /**
404      * Set horizontal cell merging status
405      * @param mergeStatus mergeStatus to set
406      */

407     public void setHMerge(int mergeStatus) {
408         this.hMerge = mergeStatus;
409     }
410
411     /**
412      * @return horizontal cell merging status
413      */

414     public int getHMerge() {
415         return this.hMerge;
416     }
417
418     /** get cell width */
419     int getCellWidth() { return this.cellWidth; }
420
421     /**
422      * Overridden so that nested tables cause extra rows to be added after the row
423      * that contains this cell
424      * disabled for V0.3 - nested table support is not done yet
425      * @throws IOException for I/O problems
426      */

427     /*
428     protected void writeRtfContent()
429     throws IOException {
430         int extraRowIndex = 0;
431         RtfTableCell extraCell = null;
432
433         for (Iterator it = getChildren().iterator(); it.hasNext();) {
434             final RtfElement e = (RtfElement)it.next();
435             if (e instanceof RtfTable) {
436                 // nested table - render its cells in supplementary rows after current row,
437                 // and put the remaining content of this cell in a new cell after nested table
438                 // Line added by Boris Poudérous
439         parentRow.getExtraRowSet().setParentITableColumnsInfo(
440                 ((RtfTable)this.getParentOfClass(e.getClass())).getITableColumnsInfo());
441         extraRowIndex = parentRow.getExtraRowSet().addTable((RtfTable)e,
442                 extraRowIndex, widthOffset);
443                 // Boris Poudérous added the passing of the current cell
444                 // attributes to the new cells (in order not to have cell without
445                 // border for example)
446         extraCell = parentRow.getExtraRowSet().createExtraCell(extraRowIndex,
447                 widthOffset, this.getCellWidth(), attrib);
448                 extraRowIndex++;
449
450             } else if (extraCell != null) {
451                 // we are after a nested table, add elements to the extra cell created for them
452                 extraCell.addChild(e);
453
454             } else {
455                 // before a nested table, normal rendering
456                 e.writeRtf();
457             }
458         }
459     }*/

460
461     /**
462      * A table cell always contains "useful" content, as it is here to take some
463      * space in a row.
464      * Use containsText() to find out if there is really some useful content in the cell.
465      * TODO: containsText could use the original isEmpty implementation?
466      * @return false (always)
467      */

468     public boolean isEmpty() {
469         return false;
470     }
471
472     /** true if the "par" control word must be written for given RtfParagraph
473      * (which is not the case for the last non-empty paragraph of the cell)
474      */

475     boolean paragraphNeedsPar(RtfParagraph p) {
476         // true if there is at least one non-empty paragraph after p in our children
477
boolean pFound = false;
478         boolean result = false;
479         for (Iterator JavaDoc it = getChildren().iterator(); it.hasNext();) {
480             final Object JavaDoc o = it.next();
481             if (!pFound) {
482                 // set pFound when p is found in the list
483
pFound = (o == p);
484             } else {
485                 if (o instanceof RtfParagraph) {
486                     final RtfParagraph p2 = (RtfParagraph)o;
487                     if (!p2.isEmpty()) {
488                         // found a non-empty paragraph after p
489
result = true;
490                         break;
491                     }
492                 } else if (o instanceof RtfTable) {
493                     break;
494                 }
495             }
496         }
497         return result;
498     }
499     
500     /**
501      * Returns the current RtfTextrun object.
502      * Opens a new one if necessary.
503      * @return The RtfTextrun object
504      * @throws IOException Thrown when an IO-problem occurs
505      */

506     public RtfTextrun getTextrun() throws IOException JavaDoc {
507         RtfAttributes attrs = new RtfAttributes();
508         
509         if (!getRow().getTable().isNestedTable()) {
510             attrs.set("intbl");
511         }
512         
513         RtfTextrun textrun = RtfTextrun.getTextrun(this, writer, attrs);
514
515         //Suppress the very last \par, because the closing \cell applies the
516
//paragraph attributes.
517
textrun.setSuppressLastPar(true);
518         
519         return textrun;
520     }
521     
522     /**
523      * Get the parent row.
524      * @return The parent row.
525      */

526     public RtfTableRow getRow() {
527         RtfElement e = this;
528         while (e.parent != null) {
529             if (e.parent instanceof RtfTableRow) {
530                 return (RtfTableRow) e.parent;
531             }
532
533             e = e.parent;
534         }
535
536         return null;
537     }
538 }
539
Popular Tags