001: /*
002: * $Id: Row.java 2748 2007-05-12 15:11:48Z blowagie $
003: * $Name$
004: *
005: * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
006: *
007: * The contents of this file are subject to the Mozilla Public License Version 1.1
008: * (the "License"); you may not use this file except in compliance with the License.
009: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
010: *
011: * Software distributed under the License is distributed on an "AS IS" basis,
012: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013: * for the specific language governing rights and limitations under the License.
014: *
015: * The Original Code is 'iText, a free JAVA-PDF library'.
016: *
017: * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
018: * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
019: * All Rights Reserved.
020: * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
021: * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
022: *
023: * Contributor(s): all the names of the contributors are added in the source code
024: * where applicable.
025: *
026: * Alternatively, the contents of this file may be used under the terms of the
027: * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
028: * provisions of LGPL are applicable instead of those above. If you wish to
029: * allow use of your version of this file only under the terms of the LGPL
030: * License and not to allow others to use your version of this file under
031: * the MPL, indicate your decision by deleting the provisions above and
032: * replace them with the notice and other provisions required by the LGPL.
033: * If you do not delete the provisions above, a recipient may use your version
034: * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE
035: *
036: * This library is free software; you can redistribute it and/or modify it
037: * under the terms of the MPL as stated above or under the terms of the GNU
038: * Library General Public License as published by the Free Software Foundation;
039: * either version 2 of the License, or any later version.
040: *
041: * This library is distributed in the hope that it will be useful, but WITHOUT
042: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
043: * FOR A PARTICULAR PURPOSE. See the GNU LIBRARY GENERAL PUBLIC LICENSE for more
044: * details.
045: *
046: * If you didn't download this code from the following link, you should check if
047: * you aren't using an obsolete version:
048: * http://www.lowagie.com/iText/
049: */
050:
051: package com.lowagie.text;
052:
053: import java.util.ArrayList;
054:
055: /**
056: * A <CODE>Row</CODE> is part of a <CODE>Table</CODE>
057: * and contains some <CODE>Cells</CODE>.
058: * <P>
059: * All <CODE>Row</CODE>s are constructed by a <CODE>Table</CODE>-object.
060: * You don't have to construct any <CODE>Row</CODE> yourself.
061: * In fact you can't construct a <CODE>Row</CODE> outside the package.
062: * <P>
063: * Since a <CODE>Cell</CODE> can span several rows and/or columns
064: * a row can contain reserved space without any content.
065: *
066: * @see Element
067: * @see Cell
068: * @see Table
069: */
070: public class Row implements Element {
071:
072: // constants
073:
074: /** id of a null element in a Row*/
075: public static final int NULL = 0;
076:
077: /** id of the Cell element in a Row*/
078: public static final int CELL = 1;
079:
080: /** id of the Table element in a Row*/
081: public static final int TABLE = 2;
082:
083: // member variables
084:
085: /** This is the number of columns in the <CODE>Row</CODE>. */
086: protected int columns;
087:
088: /** This is a valid position the <CODE>Row</CODE>. */
089: protected int currentColumn;
090:
091: /** This is the array that keeps track of reserved cells. */
092: protected boolean[] reserved;
093:
094: /** This is the array of Objects (<CODE>Cell</CODE> or <CODE>Table</CODE>). */
095: protected Object[] cells;
096:
097: /** This is the vertical alignment. */
098: protected int horizontalAlignment;
099:
100: // constructors
101:
102: /**
103: * Constructs a <CODE>Row</CODE> with a certain number of <VAR>columns</VAR>.
104: *
105: * @param columns a number of columns
106: */
107: protected Row(int columns) {
108: this .columns = columns;
109: reserved = new boolean[columns];
110: cells = new Object[columns];
111: currentColumn = 0;
112: }
113:
114: // implementation of the Element-methods
115:
116: /**
117: * Processes the element by adding it (or the different parts) to a
118: * <CODE>ElementListener</CODE>.
119: *
120: * @param listener an <CODE>ElementListener</CODE>
121: * @return <CODE>true</CODE> if the element was processed successfully
122: */
123: public boolean process(ElementListener listener) {
124: try {
125: return listener.add(this );
126: } catch (DocumentException de) {
127: return false;
128: }
129: }
130:
131: /**
132: * Gets the type of the text element.
133: *
134: * @return a type
135: */
136: public int type() {
137: return Element.ROW;
138: }
139:
140: /**
141: * Gets all the chunks in this element.
142: *
143: * @return an <CODE>ArrayList</CODE>
144: */
145: public ArrayList getChunks() {
146: return new ArrayList();
147: }
148:
149: // method to delete a column
150:
151: /**
152: * Returns a <CODE>Row</CODE> that is a copy of this <CODE>Row</CODE>
153: * in which a certain column has been deleted.
154: *
155: * @param column the number of the column to delete
156: */
157: void deleteColumn(int column) {
158: if ((column >= columns) || (column < 0)) {
159: throw new IndexOutOfBoundsException(
160: "getCell at illegal index : " + column);
161: }
162: columns--;
163: boolean newReserved[] = new boolean[columns];
164: Object newCells[] = new Cell[columns];
165:
166: for (int i = 0; i < column; i++) {
167: newReserved[i] = reserved[i];
168: newCells[i] = cells[i];
169: if (newCells[i] != null
170: && (i + ((Cell) newCells[i]).getColspan() > column)) {
171: ((Cell) newCells[i]).setColspan(((Cell) cells[i])
172: .getColspan() - 1);
173: }
174: }
175: for (int i = column; i < columns; i++) {
176: newReserved[i] = reserved[i + 1];
177: newCells[i] = cells[i + 1];
178: }
179: if (cells[column] != null
180: && ((Cell) cells[column]).getColspan() > 1) {
181: newCells[column] = cells[column];
182: ((Cell) newCells[column])
183: .setColspan(((Cell) newCells[column]).getColspan() - 1);
184: }
185: reserved = newReserved;
186: cells = newCells;
187: }
188:
189: // methods
190:
191: /**
192: * Adds a <CODE>Cell</CODE> to the <CODE>Row</CODE>.
193: *
194: * @param element the element to add (currently only Cells and Tables supported)
195: * @return the column position the <CODE>Cell</CODE> was added,
196: * or <CODE>-1</CODE> if the <CODE>element</CODE> couldn't be added.
197: */
198: int addElement(Object element) {
199: return addElement(element, currentColumn);
200: }
201:
202: /**
203: * Adds an element to the <CODE>Row</CODE> at the position given.
204: *
205: * @param element the element to add. (currently only Cells and Tables supported
206: * @param column the position where to add the cell.
207: * @return the column position the <CODE>Cell</CODE> was added,
208: * or <CODE>-1</CODE> if the <CODE>Cell</CODE> couldn't be added.
209: */
210: int addElement(Object element, int column) {
211: if (element == null)
212: throw new NullPointerException("addCell - null argument");
213: if ((column < 0) || (column > columns))
214: throw new IndexOutOfBoundsException(
215: "addCell - illegal column argument");
216: if (!((getObjectID(element) == CELL) || (getObjectID(element) == TABLE)))
217: throw new IllegalArgumentException(
218: "addCell - only Cells or Tables allowed");
219:
220: int lColspan = ((Cell.class.isInstance(element)) ? ((Cell) element)
221: .getColspan()
222: : 1);
223:
224: if (!reserve(column, lColspan)) {
225: return -1;
226: }
227:
228: cells[column] = element;
229: currentColumn += lColspan - 1;
230:
231: return column;
232: }
233:
234: /**
235: * Puts <CODE>Cell</CODE> to the <CODE>Row</CODE> at the position given, doesn't reserve colspan.
236: *
237: * @param aElement the cell to add.
238: * @param column the position where to add the cell.
239: */
240: void setElement(Object aElement, int column) {
241: if (reserved[column])
242: throw new IllegalArgumentException(
243: "setElement - position already taken");
244:
245: cells[column] = aElement;
246: if (aElement != null) {
247: reserved[column] = true;
248: }
249: }
250:
251: /**
252: * Reserves a <CODE>Cell</CODE> in the <CODE>Row</CODE>.
253: *
254: * @param column the column that has to be reserved.
255: * @return <CODE>true</CODE> if the column was reserved, <CODE>false</CODE> if not.
256: */
257: boolean reserve(int column) {
258: return reserve(column, 1);
259: }
260:
261: /**
262: * Reserves a <CODE>Cell</CODE> in the <CODE>Row</CODE>.
263: *
264: * @param column the column that has to be reserved.
265: * @param size the number of columns
266: * @return <CODE>true</CODE> if the column was reserved, <CODE>false</CODE> if not.
267: */
268: boolean reserve(int column, int size) {
269: if ((column < 0) || ((column + size) > columns))
270: throw new IndexOutOfBoundsException(
271: "reserve - incorrect column/size");
272:
273: for (int i = column; i < column + size; i++) {
274: if (reserved[i]) {
275: // undo reserve
276: for (int j = i; j >= column; j--) {
277: reserved[j] = false;
278: }
279: return false;
280: }
281: reserved[i] = true;
282: }
283: return true;
284: }
285:
286: // methods to retrieve information
287:
288: /**
289: * Returns true/false when this position in the <CODE>Row</CODE> has been reserved, either filled or through a colspan of an Element.
290: *
291: * @param column the column.
292: * @return <CODE>true</CODE> if the column was reserved, <CODE>false</CODE> if not.
293: */
294: boolean isReserved(int column) {
295: return reserved[column];
296: }
297:
298: /**
299: * Returns the type-id of the element in a Row.
300: *
301: * @param column the column of which you'd like to know the type
302: * @return the type-id of the element in the row
303: */
304: int getElementID(int column) {
305: if (cells[column] == null)
306: return NULL;
307: else if (Cell.class.isInstance(cells[column]))
308: return CELL;
309: else if (Table.class.isInstance(cells[column]))
310: return TABLE;
311:
312: return -1;
313: }
314:
315: /**
316: * Returns the type-id of an Object.
317: *
318: * @param element the object of which you'd like to know the type-id, -1 if invalid
319: * @return the type-id of an object
320: */
321: int getObjectID(Object element) {
322: if (element == null)
323: return NULL;
324: else if (Cell.class.isInstance(element))
325: return CELL;
326: else if (Table.class.isInstance(element))
327: return TABLE;
328: return -1;
329: }
330:
331: /**
332: * Gets a <CODE>Cell</CODE> or <CODE>Table</CODE> from a certain column.
333: *
334: * @param column the column the <CODE>Cell/Table</CODE> is in.
335: * @return the <CODE>Cell</CODE>,<CODE>Table</CODE> or <VAR>Object</VAR> if the column was
336: * reserved or null if empty.
337: */
338: public Object getCell(int column) {
339: if ((column < 0) || (column > columns)) {
340: throw new IndexOutOfBoundsException(
341: "getCell at illegal index :" + column + " max is "
342: + columns);
343: }
344: return cells[column];
345: }
346:
347: /**
348: * Checks if the row is empty.
349: *
350: * @return <CODE>true</CODE> if none of the columns is reserved.
351: */
352: public boolean isEmpty() {
353: for (int i = 0; i < columns; i++) {
354: if (cells[i] != null) {
355: return false;
356: }
357: }
358: return true;
359: }
360:
361: /**
362: * Gets the number of columns.
363: *
364: * @return a value
365: */
366: public int getColumns() {
367: return columns;
368: }
369:
370: /**
371: * Sets the horizontal alignment.
372: *
373: * @param value the new value
374: */
375: public void setHorizontalAlignment(int value) {
376: horizontalAlignment = value;
377: }
378:
379: /**
380: * Gets the horizontal alignment.
381: *
382: * @return a value
383: */
384: public int getHorizontalAlignment() {
385: return horizontalAlignment;
386: }
387: }
|