001: /*
002: * Copyright 2007 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.user.client.ui;
017:
018: import com.google.gwt.user.client.DOM;
019: import com.google.gwt.user.client.Element;
020:
021: /**
022: * A flexible table that creates cells on demand. It can be jagged (that is,
023: * each row can contain a different number of cells) and individual cells can be
024: * set to span multiple rows or columns.
025: * <p>
026: * <img class='gallery' src='Table.png'/>
027: * </p>
028: * <p>
029: * <h3>Example</h3>
030: * {@example com.google.gwt.examples.FlexTableExample}
031: * </p>
032: */
033: public class FlexTable extends HTMLTable {
034:
035: /**
036: * FlexTable-specific implementation of {@link HTMLTable.CellFormatter}. The
037: * formatter retrieved from {@link HTMLTable#getCellFormatter()} may be cast
038: * to this class.
039: */
040: public class FlexCellFormatter extends CellFormatter {
041:
042: /**
043: * Gets the column span for the given cell. This is the number of logical
044: * columns covered by the cell.
045: *
046: * @param row the cell's row
047: * @param column the cell's column
048: * @return the cell's column span
049: * @throws IndexOutOfBoundsException
050: */
051: public int getColSpan(int row, int column) {
052: return DOM.getElementPropertyInt(getElement(row, column),
053: "colSpan");
054: }
055:
056: /**
057: * Gets the row span for the given cell. This is the number of logical rows
058: * covered by the cell.
059: *
060: * @param row the cell's row
061: * @param column the cell's column
062: * @return the cell's row span
063: * @throws IndexOutOfBoundsException
064: */
065: public int getRowSpan(int row, int column) {
066: return DOM.getElementPropertyInt(getElement(row, column),
067: "rowSpan");
068: }
069:
070: /**
071: * Sets the column span for the given cell. This is the number of logical
072: * columns covered by the cell.
073: *
074: * @param row the cell's row
075: * @param column the cell's column
076: * @param colSpan the cell's column span
077: * @throws IndexOutOfBoundsException
078: */
079: public void setColSpan(int row, int column, int colSpan) {
080: DOM.setElementPropertyInt(ensureElement(row, column),
081: "colSpan", colSpan);
082: }
083:
084: /**
085: * Sets the row span for the given cell. This is the number of logical rows
086: * covered by the cell.
087: *
088: * @param row the cell's row
089: * @param column the cell's column
090: * @param rowSpan the cell's row span
091: * @throws IndexOutOfBoundsException
092: */
093: public void setRowSpan(int row, int column, int rowSpan) {
094: DOM.setElementPropertyInt(ensureElement(row, column),
095: "rowSpan", rowSpan);
096: }
097: }
098:
099: private static native void addCells(Element table, int row, int num)/*-{
100: var rowElem = table.rows[row];
101: for(var i = 0; i < num; i++){
102: var cell = $doc.createElement("td");
103: rowElem.appendChild(cell);
104: }
105: }-*/;
106:
107: public FlexTable() {
108: super ();
109: setCellFormatter(new FlexCellFormatter());
110: setRowFormatter(new RowFormatter());
111: setColumnFormatter(new ColumnFormatter());
112: }
113:
114: /**
115: * Appends a cell to the specified row.
116: *
117: * @param row the row to which the new cell will be added
118: * @throws IndexOutOfBoundsException
119: */
120: public void addCell(int row) {
121: insertCell(row, getCellCount(row));
122: }
123:
124: /**
125: * Gets the number of cells on a given row.
126: *
127: * @param row the row whose cells are to be counted
128: * @return the number of cells present
129: * @throws IndexOutOfBoundsException
130: */
131: @Override
132: public int getCellCount(int row) {
133: checkRowBounds(row);
134: return super .getDOMCellCount(getBodyElement(), row);
135: }
136:
137: /**
138: * Explicitly gets the {@link FlexCellFormatter}. The results of
139: * {@link HTMLTable#getCellFormatter()} may also be downcast to a
140: * {@link FlexCellFormatter}.
141: *
142: * @return the FlexTable's cell formatter
143: */
144: public FlexCellFormatter getFlexCellFormatter() {
145: return (FlexCellFormatter) getCellFormatter();
146: }
147:
148: /**
149: * Gets the number of rows.
150: *
151: * @return number of rows
152: */
153: @Override
154: public int getRowCount() {
155: return getDOMRowCount();
156: }
157:
158: /**
159: * Inserts a cell into the FlexTable.
160: *
161: * @param beforeRow the cell's row
162: * @param beforeColumn the cell's column
163: */
164: @Override
165: public void insertCell(int beforeRow, int beforeColumn) {
166: super .insertCell(beforeRow, beforeColumn);
167: }
168:
169: /**
170: * Inserts a row into the FlexTable.
171: *
172: * @param beforeRow the row to insert
173: */
174: @Override
175: public int insertRow(int beforeRow) {
176: return super .insertRow(beforeRow);
177: }
178:
179: /**
180: * @see com.google.gwt.user.client.ui.HTMLTable#removeCell(int, int)
181: */
182: @Override
183: public void removeCell(int row, int col) {
184: super .removeCell(row, col);
185: }
186:
187: /**
188: * Removes a number of cells from a row in the table.
189: *
190: * @param row the row of the cells to be removed
191: * @param column the column of the first cell to be removed
192: * @param num the number of cells to be removed
193: * @throws IndexOutOfBoundsException
194: */
195: public void removeCells(int row, int column, int num) {
196: for (int i = 0; i < num; i++) {
197: removeCell(row, column);
198: }
199: }
200:
201: @Override
202: public void removeRow(int row) {
203: super .removeRow(row);
204: }
205:
206: /**
207: * Ensure that the cell exists.
208: *
209: * @param row the row to prepare.
210: * @param column the column to prepare.
211: * @throws IndexOutOfBoundsException if the row is negative
212: */
213: @Override
214: protected void prepareCell(int row, int column) {
215: prepareRow(row);
216: if (column < 0) {
217: throw new IndexOutOfBoundsException(
218: "Cannot create a column with a negative index: "
219: + column);
220: }
221:
222: // Ensure that the requested column exists.
223: int cellCount = getCellCount(row);
224: int required = column + 1 - cellCount;
225: if (required > 0) {
226: addCells(getBodyElement(), row, required);
227: }
228: }
229:
230: /**
231: * Ensure that the row exists.
232: *
233: * @param row The row to prepare.
234: * @throws IndexOutOfBoundsException if the row is negative
235: */
236: @Override
237: protected void prepareRow(int row) {
238: if (row < 0) {
239: throw new IndexOutOfBoundsException(
240: "Cannot create a row with a negative index: " + row);
241: }
242:
243: // Ensure that the requested row exists.
244: int rowCount = getRowCount();
245: for (int i = rowCount; i <= row; i++) {
246: insertRow(i);
247: }
248: }
249: }
|