KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > fo > flow > TableCell


1 /*
2  * $Id: TableCell.java,v 1.39.2.10 2003/04/11 00:24:39 pietsch Exp $
3  * ============================================================================
4  * The Apache Software License, Version 1.1
5  * ============================================================================
6  *
7  * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without modifica-
10  * tion, are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. The end-user documentation included with the redistribution, if any, must
20  * include the following acknowledgment: "This product includes software
21  * developed by the Apache Software Foundation (http://www.apache.org/)."
22  * Alternately, this acknowledgment may appear in the software itself, if
23  * and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. The names "FOP" and "Apache Software Foundation" must not be used to
26  * endorse or promote products derived from this software without prior
27  * written permission. For written permission, please contact
28  * apache@apache.org.
29  *
30  * 5. Products derived from this software may not be called "Apache", nor may
31  * "Apache" appear in their name, without prior written permission of the
32  * Apache Software Foundation.
33  *
34  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
35  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
37  * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
39  * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
40  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
41  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
43  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44  * ============================================================================
45  *
46  * This software consists of voluntary contributions made by many individuals
47  * on behalf of the Apache Software Foundation and was originally created by
48  * James Tauber <jtauber@jtauber.com>. For more information on the Apache
49  * Software Foundation, please see <http://www.apache.org/>.
50  */

51 package org.apache.fop.fo.flow;
52
53 // FOP
54
import org.apache.fop.fo.*;
55 import org.apache.fop.fo.properties.*;
56 import org.apache.fop.layout.*;
57 import org.apache.fop.apps.FOPException;
58
59 public class TableCell extends FObj {
60
61     public static class Maker extends FObj.Maker {
62         public FObj make(FObj parent, PropertyList propertyList,
63                         String JavaDoc systemId, int line, int column)
64             throws FOPException {
65             return new TableCell(parent, propertyList, systemId, line, column);
66         }
67
68     }
69
70     public static FObj.Maker maker() {
71         return new TableCell.Maker();
72     }
73
74     // int spaceBefore;
75
// int spaceAfter;
76

77     String JavaDoc id;
78     int numColumnsSpanned;
79     int numRowsSpanned;
80     int iColNumber = -1; // uninitialized
81

82     /**
83      * Offset of content rectangle in inline-progression-direction,
84      * relative to table.
85      */

86     protected int startOffset;
87
88     /**
89      * Dimension of allocation rectangle in inline-progression-direction,
90      * determined by the width of the column(s) occupied by the cell
91      */

92     protected int width;
93
94     /**
95      * Offset of content rectangle, in block-progression-direction,
96      * relative to the row.
97      */

98     protected int beforeOffset = 0;
99
100     /**
101      * Offset of content rectangle, in inline-progression-direction,
102      * relative to the column start edge.
103      */

104     protected int startAdjust = 0;
105
106     /**
107      * Adjust to theoretical column width to obtain content width
108      * relative to the column start edge.
109      */

110     protected int widthAdjust = 0;
111
112     /* For collapsed border style */
113     protected int borderHeight = 0;
114
115     /**
116      * Minimum ontent height of cell.
117      */

118     protected int minCellHeight = 0;
119
120     protected int height = 0;
121     protected int top; // Ypos of cell ???
122
protected int verticalAlign;
123     protected boolean bRelativeAlign = false;
124
125     // boolean setup = false;
126
boolean bSepBorders = true;
127     
128     /**
129      * Set to true if all content completely laid out.
130      */

131     boolean bDone=false;
132
133     /**
134      * Border separation value in the block-progression dimension.
135      * Used in calculating cells height.
136      */

137     int m_borderSeparation = 0;
138
139     AreaContainer cellArea;
140
141     public TableCell(FObj parent, PropertyList propertyList,
142                         String JavaDoc systemId, int line, int column)
143         throws FOPException {
144         super(parent, propertyList, systemId, line, column);
145         if (!(parent instanceof TableRow)) {
146             throw new FOPException("A table cell must be child of fo:table-row,"
147                                    + " not " + parent.getName(), systemId, line, column);
148         }
149         doSetup(); // init some basic property values
150
}
151
152     public String JavaDoc getName() {
153         return "fo:table-cell";
154     }
155
156     // Set position relative to table (set by body?)
157
public void setStartOffset(int offset) {
158         startOffset = offset;
159     }
160
161     // Initially same as the column width containg this cell or the
162
// sum of the spanned columns if numColumnsSpanned > 1
163
public void setWidth(int width) {
164         this.width = width;
165     }
166
167     public int getColumnNumber() {
168         return iColNumber;
169     }
170
171     public int getNumColumnsSpanned() {
172         return numColumnsSpanned;
173     }
174
175     public int getNumRowsSpanned() {
176         return numRowsSpanned;
177     }
178
179     public void doSetup() // throws FOPException
180
{
181         // Common Accessibility Properties
182
AccessibilityProps mAccProps = propMgr.getAccessibilityProps();
183
184         // Common Aural Properties
185
AuralProps mAurProps = propMgr.getAuralProps();
186
187         // Common Border, Padding, and Background Properties
188
BorderAndPadding bap = propMgr.getBorderAndPadding();
189         BackgroundProps bProps = propMgr.getBackgroundProps();
190
191         // Common Relative Position Properties
192
RelativePositionProps mRelProps = propMgr.getRelativePositionProps();
193
194         // this.properties.get("border-after-precedence");
195
// this.properties.get("border-before-precendence");
196
// this.properties.get("border-end-precendence");
197
// this.properties.get("border-start-precendence");
198
// this.properties.get("block-progression-dimension");
199
// this.properties.get("column-number");
200
// this.properties.get("display-align");
201
// this.properties.get("relative-align");
202
// this.properties.get("empty-cells");
203
// this.properties.get("ends-row");
204
// this.properties.get("height");
205
// this.properties.get("id");
206
// this.properties.get("number-columns-spanned");
207
// this.properties.get("number-rows-spanned");
208
// this.properties.get("starts-row");
209
// this.properties.get("width");
210

211         this.iColNumber =
212             properties.get("column-number").getNumber().intValue();
213         if (iColNumber < 0) {
214             iColNumber = 0;
215         }
216         this.numColumnsSpanned =
217             this.properties.get("number-columns-spanned").getNumber().intValue();
218         if (numColumnsSpanned < 1) {
219             numColumnsSpanned = 1;
220         }
221         this.numRowsSpanned =
222             this.properties.get("number-rows-spanned").getNumber().intValue();
223         if (numRowsSpanned < 1) {
224             numRowsSpanned = 1;
225         }
226
227         this.id = this.properties.get("id").getString();
228
229         bSepBorders = (this.properties.get("border-collapse").getEnum()
230                        == BorderCollapse.SEPARATE);
231
232         calcBorders(propMgr.getBorderAndPadding());
233
234         // Vertical cell alignment
235
verticalAlign = this.properties.get("display-align").getEnum();
236         if (verticalAlign == DisplayAlign.AUTO) {
237             // Depends on all cells starting in row
238
bRelativeAlign = true;
239             verticalAlign = this.properties.get("relative-align").getEnum();
240         } else
241             bRelativeAlign = false; // Align on a per-cell basis
242

243         this.minCellHeight =
244             this.properties.get("height").getLength().mvalue();
245     }
246
247
248     public int layout(Area area) throws FOPException {
249         int originalAbsoluteHeight = area.getAbsoluteHeight();
250         if (this.marker == BREAK_AFTER) {
251             return Status.OK;
252         }
253
254         if (this.marker == START) {
255             // if (!setup) {
256
// doSetup(area);
257
// }
258

259             // Calculate cell borders
260
// calcBorders(propMgr.getBorderAndPadding());
261

262             try {
263                 area.getIDReferences().createID(id);
264             }
265             catch(FOPException e) {
266                 if (!e.isLocationSet()) {
267                     e.setLocation(systemId, line, column);
268                 }
269                 throw e;
270             }
271
272             this.marker = 0;
273             this.bDone=false;
274         }
275
276         /*
277          * if ((spaceBefore != 0) && (this.marker ==0)) {
278          * area.increaseHeight(spaceBefore);
279          * }
280          */

281
282         if (marker == 0) {
283             // configure id
284
area.getIDReferences().configureID(id, area);
285         }
286
287         // int spaceLeft = area.spaceLeft() - m_borderSeparation/2 + borderHeight/2 ;
288
int spaceLeft = area.spaceLeft() - m_borderSeparation;
289         // The Area position defines the content rectangle! Borders
290
// and padding are outside of this rectangle.
291
this.cellArea =
292             new AreaContainer(propMgr.getFontState(area.getFontInfo()),
293                               startOffset + startAdjust, beforeOffset,
294                               width - widthAdjust, spaceLeft,
295                               Position.RELATIVE);
296
297         cellArea.foCreator = this; // G Seshadri
298
cellArea.setPage(area.getPage());
299         cellArea.setParent(area);
300         try {
301             cellArea.setBorderAndPadding((BorderAndPadding)
302                     propMgr.getBorderAndPadding().clone());
303         } catch (CloneNotSupportedException JavaDoc e) {
304             System.err.println("Can't clone BorderAndPadding: " + e) ;
305             cellArea.setBorderAndPadding(propMgr.getBorderAndPadding());
306         }
307         cellArea.setBackground(propMgr.getBackgroundProps());
308         cellArea.start();
309
310         cellArea.setAbsoluteHeight(area.getAbsoluteHeight()); // ???
311
cellArea.setIDReferences(area.getIDReferences());
312         // Add adjust for padding and border to fix link alignment!
313
cellArea.setTableCellXOffset(startOffset + startAdjust);
314
315         int numChildren = this.children.size();
316         for (int i = this.marker; bDone==false && i < numChildren; i++) {
317             FObj fo = (FObj)children.get(i);
318             fo.setIsInTableCell();
319             fo.forceWidth(width); // ???
320

321             // Overflows may cause a row to be re-layedout,
322
// need to pass already processed content.
323
this.marker = i;
324
325             int status;
326             if (Status.isIncomplete((status = fo.layout(cellArea)))) {
327                 // this.marker = i;
328
if ((i == 0) && (status == Status.AREA_FULL_NONE)) {
329                     return Status.AREA_FULL_NONE;
330                 } else {
331                     // hani Elabed 11/21/2000
332
area.addChild(cellArea);
333                     // area.setAbsoluteHeight(cellArea.getAbsoluteHeight());
334
return Status.AREA_FULL_SOME;
335                 }
336             }
337
338             area.setMaxHeight(area.getMaxHeight() - spaceLeft
339                               + this.cellArea.getMaxHeight());
340         }
341         this.bDone=true;
342         cellArea.end();
343         area.addChild(cellArea);
344
345         // Adjust for minimum cell content height
346
if (minCellHeight > cellArea.getContentHeight()) {
347             cellArea.setHeight(minCellHeight);
348         }
349
350         // This is the allocation height of the cell (including borders
351
// and padding
352
// ALSO need to include offsets if using "separate borders"
353
height = cellArea.getHeight();
354         top = cellArea.getCurrentYPosition(); // CHECK THIS!!!
355

356         // reset absoluteHeight to beginning of row
357
// area.setHeight(cellArea.getHeight() + spaceBefore + spaceAfter);
358
// I don't think we should do this here (KL) !!!
359
// area.setHeight(cellArea.getHeight());
360
// area.setAbsoluteHeight(originalAbsoluteHeight);
361

362         return Status.OK;
363     }
364
365     /**
366      * Return the allocation height of the cell area.
367      * Note: called by TableRow.
368      * We adjust the actual allocation height of the area by the value
369      * of border separation (for separate borders) or border height
370      * adjustment for collapse style (because current scheme makes cell
371      * overestimate the allocation height).
372      */

373     public int getHeight() {
374         return cellArea.getHeight() + m_borderSeparation - borderHeight;
375     }
376
377     /**
378      * Set the final size of cell content rectangles to the actual row height
379      * and to vertically align the actual content within the cell rectangle.
380      * @param h Height of this row in the grid which is based on
381      * the allocation height of all the cells in the row, including any
382      * border separation values.
383      */

384     public void setRowHeight(int h) {
385         int delta = h - getHeight();
386         // cellArea.increaseHeight(h + borderHeight/2 - cellArea.getHeight());
387
if (bRelativeAlign) {
388             // Must get info for all cells starting in row!
389
// verticalAlign can be BEFORE or BASELINE
390
// For now just treat like "before"
391
cellArea.increaseHeight(delta);
392         } else if (delta > 0) {
393             BorderAndPadding cellBP = cellArea.getBorderAndPadding();
394             switch (verticalAlign) {
395             case DisplayAlign.CENTER:
396                 // Increase cell padding before and after and change
397
// "Y" position of content rectangle
398
cellArea.shiftYPosition(delta / 2);
399                 cellBP.setPaddingLength(BorderAndPadding.TOP,
400                                         cellBP.getPaddingTop(false)
401                                         + delta / 2);
402                 cellBP.setPaddingLength(BorderAndPadding.BOTTOM,
403                                         cellBP.getPaddingBottom(false)
404                                         + delta - delta / 2);
405                 break;
406             case DisplayAlign.AFTER:
407                 // Increase cell padding before and change
408
// "Y" position of content rectangle
409
cellBP.setPaddingLength(BorderAndPadding.TOP,
410                                         cellBP.getPaddingTop(false) + delta);
411                 cellArea.shiftYPosition(delta);
412                 break;
413             case DisplayAlign.BEFORE:
414                 // cellArea.increaseHeight(delta);
415
cellBP.setPaddingLength(BorderAndPadding.BOTTOM,
416                                         cellBP.getPaddingBottom(false)
417                                         + delta);
418
419             default: // OK
420
break;
421             }
422         }
423     }
424
425     /**
426      * Calculate cell border and padding, including offset of content
427      * rectangle from the theoretical grid position.
428      */

429     private void calcBorders(BorderAndPadding bp) {
430         if (this.bSepBorders) {
431             /*
432              * Easy case.
433              * Cell border is the property specified directly on cell.
434              * Offset content rect by half the border-separation value,
435              * in addition to the border and padding values. Note:
436              * border-separate should only be specified on the table object,
437              * but it inherits.
438              */

439             int iSep =
440                 properties.get("border-separation.inline-progression-direction").getLength().mvalue();
441              //border-spacing is a shorthand of border-separation
442
int iSpacing =
443                 properties.get("border-spacing.inline-progression-direction").getLength().mvalue();
444             if (iSpacing > iSep)
445                 iSep = iSpacing;
446             this.startAdjust = iSep / 2 + bp.getBorderLeftWidth(false)
447                                + bp.getPaddingLeft(false);
448             /*
449              * int contentOffset = iSep + bp.getBorderStartWidth(false) +
450              * bp.getPaddingStart(false);
451              */

452             this.widthAdjust = startAdjust + iSep - iSep / 2
453                                + bp.getBorderRightWidth(false)
454                                + bp.getPaddingRight(false);
455             // bp.getBorderEndWidth(false) + bp.getPaddingEnd(false);
456
// Offset of content rectangle in the block-progression direction
457
m_borderSeparation =
458                 properties.get("border-separation.block-progression-direction").getLength().mvalue();
459             int m_borderSpacing =
460                 properties.get("border-spacing.block-progression-direction").getLength().mvalue();
461             if (m_borderSpacing > m_borderSeparation)
462                 m_borderSeparation = m_borderSpacing;
463             this.beforeOffset = m_borderSeparation / 2
464                                 + bp.getBorderTopWidth(false)
465                                 + bp.getPaddingTop(false);
466             // bp.getBorderBeforeWidth(false) + bp.getPaddingBefore(false);
467

468         } else {
469             // System.err.println("Collapse borders");
470
/*
471              * Hard case.
472              * Cell border is combination of other cell borders, or table
473              * border for edge cells. Also seems to border values specified
474              * on row and column FO in the table (if I read CR correclty.)
475              */

476
477             // Set up before and after borders, taking into account row
478
// and table border properties.
479
// ??? What about table-body, header,footer
480

481             /*
482              * We can't calculate before and after because we aren't sure
483              * whether this row will be the first or last in its area, due
484              * to redoing break decisions (at least in the "new" architecture.)
485              * So in the general case, we will calculate two possible values:
486              * the first/last one and the "middle" one.
487              * Example: border-before
488              * 1. If the cell is in the first row in the first table body, it
489              * will combine with the last row of the header, or with the
490              * top (before) table border if there is no header.
491              * 2. Otherwise there are two cases:
492              * a. the row is first in its (non-first) Area.
493              * The border can combine with either:
494              * i. the last row of table-header and its cells, or
495              * ii. the table before border (no table-header or it is
496              * omitted on non-first Areas).
497              * b. the row isn't first in its Area.
498              * The border combines with the border of the previous
499              * row and the cells which end in that row.
500              */

501
502             /*
503              * if-first
504              * Calculate the effective border of the cell before-border,
505              * it's parent row before-border, the last header row after-border,
506              * the after border of the cell(s) which end in the last header
507              * row.
508              */

509             /*
510              * if-not-first
511              * Calculate the effective border of the cell before-border,
512              * it's parent row before-border, the previous row after-border,
513              * the after border of the cell(s) which end in the previous
514              * row.
515              */

516
517
518             /* ivan demakov */
519             int borderStart = bp.getBorderLeftWidth(false);
520             int borderEnd = bp.getBorderRightWidth(false);
521             int borderBefore = bp.getBorderTopWidth(false);
522             int borderAfter = bp.getBorderBottomWidth(false);
523
524             this.startAdjust = borderStart / 2 + bp.getPaddingLeft(false);
525
526             this.widthAdjust = startAdjust + borderEnd / 2
527                                + bp.getPaddingRight(false);
528             this.beforeOffset = borderBefore / 2 + bp.getPaddingTop(false);
529             // Half border height to fix overestimate of area size!
530
this.borderHeight = (borderBefore + borderAfter) / 2;
531         }
532     }
533     
534
535 }
536
Popular Tags