001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /* $Id: GridUnit.java 521744 2007-03-23 14:37:19Z jeremias $ */
019:
020: package org.apache.fop.layoutmgr.table;
021:
022: import org.apache.commons.logging.Log;
023: import org.apache.commons.logging.LogFactory;
024: import org.apache.fop.fo.FONode;
025: import org.apache.fop.fo.flow.Table;
026: import org.apache.fop.fo.flow.TableBody;
027: import org.apache.fop.fo.flow.TableCell;
028: import org.apache.fop.fo.flow.TableColumn;
029: import org.apache.fop.fo.flow.TableRow;
030: import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
031: import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
032:
033: /**
034: * This class represents one grid unit inside a table.
035: */
036: public class GridUnit {
037:
038: private static Log log = LogFactory.getLog(GridUnit.class);
039:
040: /** Indicates that the grid unit is in the first column. */
041: public static final int IN_FIRST_COLUMN = 0;
042: /** Indicates that the grid unit is in the last column. */
043: public static final int IN_LAST_COLUMN = 1;
044: /** Indicates that the grid unit is in the first row of the table. */
045: public static final int FIRST_IN_TABLE = 2;
046: /** Indicates that the grid unit is in the first row of the table part (header, footer, body). */
047: public static final int FIRST_IN_PART = 3;
048: /** Indicates that the grid unit is in the last row of the table part (header, footer, body). */
049: public static final int LAST_IN_PART = 4;
050: /** Indicates that the grid unit is in the last row of the table. */
051: public static final int LAST_IN_TABLE = 5;
052: /** Indicates that the primary grid unit has a pending keep-with-next. */
053: public static final int KEEP_WITH_NEXT_PENDING = 6;
054: /** Indicates that the primary grid unit has a pending keep-with-previous. */
055: public static final int KEEP_WITH_PREVIOUS_PENDING = 7;
056:
057: /** Primary grid unit */
058: private PrimaryGridUnit primary;
059: /** Table cell which occupies this grid unit */
060: private TableCell cell;
061: /** Table row which occupies this grid unit (may be null) */
062: private TableRow row;
063: /** Table column that this grid unit belongs to */
064: private TableColumn column;
065:
066: /** start index of grid unit within row in column direction */
067: private int startCol;
068: /** index of grid unit within cell in column direction */
069: private int colSpanIndex;
070: /** index of grid unit within cell in row direction */
071: private int rowSpanIndex;
072: /** effective borders for a cell slot */
073: private CommonBorderPaddingBackground effectiveBorders;
074: /** flags for the grid unit */
075: private byte flags = 0;
076:
077: /**
078: * Creates a new grid unit.
079: *
080: * @param cell table cell which occupies this grid unit
081: * @param column table column this grid unit belongs to
082: * @param startCol index of the column this grid unit belongs to
083: * @param colSpanIndex index of this grid unit in the span, in column direction
084: */
085: public GridUnit(TableCell cell, TableColumn column, int startCol,
086: int colSpanIndex) {
087: this (null, cell, column, startCol, colSpanIndex);
088: }
089:
090: /**
091: * Creates a new grid unit.
092: *
093: * @param primary the before-start grid unit of the cell containing this grid unit
094: * @param column table column this grid unit belongs to
095: * @param startCol index of the column this grid unit belongs to
096: * @param colSpanIndex index of this grid unit in the span, in column direction
097: */
098: public GridUnit(PrimaryGridUnit primary, TableColumn column,
099: int startCol, int colSpanIndex) {
100: this (primary, primary.getCell(), column, startCol, colSpanIndex);
101: }
102:
103: /**
104: * Creates a new grid unit.
105: *
106: * @param primary the before-start grid unit of the cell containing this grid unit
107: * @param cell table cell which occupies this grid unit
108: * @param column table column this grid unit belongs to
109: * @param startCol index of the column this grid unit belongs to
110: * @param colSpanIndex index of this grid unit in the span, in column direction
111: */
112: protected GridUnit(PrimaryGridUnit primary, TableCell cell,
113: TableColumn column, int startCol, int colSpanIndex) {
114: this .primary = primary;
115: this .cell = cell;
116: this .column = column;
117: this .startCol = startCol;
118: this .colSpanIndex = colSpanIndex;
119: }
120:
121: public TableCell getCell() {
122: return cell;
123: }
124:
125: public TableColumn getColumn() {
126: return column;
127: }
128:
129: public TableRow getRow() {
130: if (row != null) {
131: return row;
132: } else if (getCell().getParent() instanceof TableRow) {
133: return (TableRow) getCell().getParent();
134: } else {
135: return null;
136: }
137: }
138:
139: /**
140: * Sets the table-row FO, if applicable.
141: * @param row the table-row FO
142: */
143: public void setRow(TableRow row) {
144: this .row = row;
145: }
146:
147: public TableBody getBody() {
148: FONode node = getCell();
149: while (node != null && !(node instanceof TableBody)) {
150: node = node.getParent();
151: }
152: return (TableBody) node;
153: }
154:
155: public Table getTable() {
156: FONode node = getBody();
157: while (node != null && !(node instanceof Table)) {
158: node = node.getParent();
159: }
160: if (node == null && getColumn() != null) {
161: node = getColumn().getParent();
162: }
163: return (Table) node;
164: }
165:
166: /**
167: * Returns the before-start grid unit of the cell containing this grid unit.
168: *
169: * @return the before-start grid unit of the cell containing this grid unit.
170: */
171: public PrimaryGridUnit getPrimary() {
172: return (isPrimary() ? (PrimaryGridUnit) this : primary);
173: }
174:
175: /**
176: * Is this grid unit the before-start grid unit of the cell?
177: *
178: * @return true if this grid unit is the before-start grid unit of the cell
179: */
180: public boolean isPrimary() {
181: return false;
182: }
183:
184: /**
185: * Does this grid unit belong to an empty cell?
186: *
187: * @return true if this grid unit belongs to an empty cell
188: */
189: public boolean isEmpty() {
190: return cell == null;
191: }
192:
193: public int getStartCol() {
194: return startCol;
195: }
196:
197: /** @return true if the grid unit is the last in column spanning direction */
198: public boolean isLastGridUnitColSpan() {
199: if (cell != null) {
200: return (colSpanIndex == cell.getNumberColumnsSpanned() - 1);
201: } else {
202: return true;
203: }
204: }
205:
206: /** @return true if the grid unit is the last in row spanning direction */
207: public boolean isLastGridUnitRowSpan() {
208: if (cell != null) {
209: return (rowSpanIndex == cell.getNumberRowsSpanned() - 1);
210: } else {
211: return true;
212: }
213: }
214:
215: /**
216: * @return the index of the grid unit inside a cell in row direction
217: */
218: public int getRowSpanIndex() {
219: return rowSpanIndex;
220: }
221:
222: /**
223: * @return the index of the grid unit inside a cell in column direction
224: */
225: public int getColSpanIndex() {
226: return colSpanIndex;
227: }
228:
229: /**
230: * Returns a BorderInfo instance for a side of the currently applicable cell before border
231: * resolution (i.e. the value from the FO). A return value of null indicates an empty cell.
232: * See CollapsingBorderModel(EyeCatching) where this method is used.
233: * @param side for which side to return the BorderInfo
234: * @return the requested BorderInfo instance or null if the grid unit is an empty cell
235: */
236: public BorderInfo getOriginalBorderInfoForCell(int side) {
237: if (cell != null) {
238: return cell.getCommonBorderPaddingBackground()
239: .getBorderInfo(side);
240: } else {
241: return null;
242: }
243: }
244:
245: /**
246: * @return the resolved normal borders for this grid unit
247: */
248: public CommonBorderPaddingBackground getBorders() {
249: return effectiveBorders;
250: }
251:
252: /**
253: * @return true if the grid unit has any borders.
254: */
255: public boolean hasBorders() {
256: return (getBorders() != null) && getBorders().hasBorder();
257: }
258:
259: /**
260: * Assigns the borders from the given cell to this cell info. Used in
261: * case of separate border model.
262: */
263: public void assignBorderForSeparateBorderModel() {
264: if (cell != null) {
265: effectiveBorders = cell.getCommonBorderPaddingBackground();
266: }
267: }
268:
269: /**
270: * Resolve collapsing borders for the given cell. Used in case of the collapsing border model.
271: * @param other neighbouring grid unit if any
272: * @param side the side to resolve (one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END)
273: */
274: public void resolveBorder(GridUnit other, int side) {
275: resolveBorder(other, side, 0);
276: }
277:
278: /**
279: * Resolve collapsing borders for the given cell. Used in case of the collapsing border model.
280: * @param other neighbouring grid unit if any
281: * @param side the side to resolve (one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END)
282: * @param resFlags flags for the border resolution
283: */
284: public void resolveBorder(GridUnit other, int side, int resFlags) {
285: CollapsingBorderModel borderModel = CollapsingBorderModel
286: .getBorderModelFor(getTable().getBorderCollapse());
287: if (effectiveBorders == null) {
288: effectiveBorders = new CommonBorderPaddingBackground();
289: }
290: effectiveBorders.setBorderInfo(borderModel.determineWinner(
291: this , other, side, resFlags), side);
292: if (cell != null) {
293: effectiveBorders.setPadding(cell
294: .getCommonBorderPaddingBackground());
295: }
296: if (log.isDebugEnabled()) {
297: log.debug(this + " resolved borders: " + "before="
298: + effectiveBorders.getBorderBeforeWidth(false)
299: + ", " + "after="
300: + effectiveBorders.getBorderAfterWidth(false)
301: + ", " + "start="
302: + effectiveBorders.getBorderStartWidth(false)
303: + ", " + "end="
304: + effectiveBorders.getBorderEndWidth(false));
305: }
306: }
307:
308: /**
309: * Returns a flag for this GridUnit.
310: * @param which the requested flag
311: * @return the value of the flag
312: */
313: public boolean getFlag(int which) {
314: return (flags & (1 << which)) != 0;
315: }
316:
317: /**
318: * Sets a flag on a GridUnit.
319: * @param which the flag to set
320: * @param value the new value for the flag
321: */
322: public void setFlag(int which, boolean value) {
323: if (value) {
324: flags |= (1 << which); //set flag
325: } else {
326: flags &= ~(1 << which); //clear flag
327: }
328: }
329:
330: /**
331: * @return the grid unit just below this grid unit if the cell is spanning.
332: */
333: public GridUnit createNextRowSpanningGridUnit() {
334: if (isLastGridUnitRowSpan()) {
335: return null;
336: } else {
337: //cloning the current GridUnit with adjustments
338: GridUnit gu = new GridUnit(getPrimary(), getColumn(),
339: startCol, colSpanIndex);
340: gu.rowSpanIndex = rowSpanIndex + 1;
341: return gu;
342: }
343: }
344:
345: /** @see java.lang.Object#toString() */
346: public String toString() {
347: StringBuffer buffer = new StringBuffer();
348: if (isEmpty()) {
349: buffer.append("EMPTY");
350: } else if (isPrimary()) {
351: buffer.append("Primary");
352: }
353: buffer.append("GridUnit:");
354: if (colSpanIndex > 0) {
355: buffer.append(" colSpan=").append(colSpanIndex);
356: if (isLastGridUnitColSpan()) {
357: buffer.append("(last)");
358: }
359: }
360: if (rowSpanIndex > 0) {
361: buffer.append(" rowSpan=").append(rowSpanIndex);
362: if (isLastGridUnitRowSpan()) {
363: buffer.append("(last)");
364: }
365: }
366: buffer.append(" startCol=").append(startCol);
367: if (!isPrimary() && getPrimary() != null) {
368: buffer.append(" primary=").append(
369: getPrimary().getStartRow());
370: buffer.append("/").append(getPrimary().getStartCol());
371: if (getPrimary().getCell() != null) {
372: buffer.append(" id=" + getPrimary().getCell().getId());
373: }
374: }
375: buffer.append(" flags=").append(Integer.toBinaryString(flags));
376: return buffer.toString();
377: }
378:
379: }
|