com.google.gwt.user.client.ui.Grid Maven / Gradle / Ivy
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.user.client.ui;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
/**
* A rectangular grid that can contain text, html, or a child
* {@link com.google.gwt.user.client.ui.Widget} within its cells. It must be
* resized explicitly to the desired number of rows and columns.
*
*
*
*
*
Example
* {@example com.google.gwt.examples.GridExample}
*
*
* Use in UiBinder Templates
*
* Grid widget consists of <g:row> elements. Each <g:row> element
* can contain one or more <g:cell> or <g:customCell> elements.
* Using <g:cell> attribute it is possible to place pure HTML content.
* <g:customCell> is used as a container for
* {@link com.google.gwt.user.client.ui.Widget} type objects. (Note that the
* tags of the row, cell and customCell elements are not capitalized. This
* is meant to signal that the item is not a runtime object, and so cannot
* have a ui:field
attribute.)
*
* For example:
*
*
* <g:Grid>
* <g:row styleName="optionalHeaderStyle">
* <g:customCell styleName="optionalFooCellStyle">
* <g:Label>foo</g:Label>
* </g:customCell>
* <g:customCell styleName="optionalBarCellStyle">
* <g:Label>bar</g:Label>
* </g:customCell>
* </g:row>
* <g:row>
* <g:cell>
* <div>foo</div>
* </g:cell>
* <g:cell>
* <div>bar</div>
* </g:cell>
* </g:row>
* </g:Grid>
*
*/
public class Grid extends HTMLTable {
/**
* Native method to add rows into a table with a given number of columns.
*
* @param table the table element
* @param rows number of rows to add
* @param columns the number of columns per row
*/
private static native void addRows(Element table, int rows, int columns) /*-{
var td = $doc.createElement("td");
td.innerHTML = " ";
var row = $doc.createElement("tr");
for(var cellNum = 0; cellNum < columns; cellNum++) {
var cell = td.cloneNode(true);
row.appendChild(cell);
}
table.appendChild(row);
for(var rowNum = 1; rowNum < rows; rowNum++) {
table.appendChild(row.cloneNode(true));
}
}-*/;
/**
* Number of columns in the current grid.
*/
protected int numColumns;
/**
* Number of rows in the current grid.
*/
protected int numRows;
/**
* Constructor for Grid
.
*/
public Grid() {
super();
setCellFormatter(new CellFormatter());
setRowFormatter(new RowFormatter());
setColumnFormatter(new ColumnFormatter());
}
/**
* Constructs a grid with the requested size.
*
* @param rows the number of rows
* @param columns the number of columns
* @throws IndexOutOfBoundsException
*/
public Grid(int rows, int columns) {
this();
resize(rows, columns);
}
/**
* Replaces the contents of the specified cell with a single space.
*
* @param row the cell's row
* @param column the cell's column
* @throws IndexOutOfBoundsException
*/
@Override
public boolean clearCell(int row, int column) {
Element td = getCellFormatter().getElement(row, column);
boolean b = internalClearCell(td, false);
DOM.setInnerHTML(td, " ");
return b;
}
/**
* Return number of columns. For grid, row argument is ignored as all grids
* are rectangular.
*/
@Override
public int getCellCount(int row) {
return numColumns;
}
/**
* Gets the number of columns in this grid.
*
* @return the number of columns
*/
public int getColumnCount() {
return numColumns;
}
/**
* Return number of rows.
*/
@Override
public int getRowCount() {
return numRows;
}
/**
* Inserts a new row into the table. If you want to add multiple rows at once,
* use {@link #resize(int, int)} or {@link #resizeRows(int)} as they are more
* efficient.
*
* @param beforeRow the index before which the new row will be inserted
* @return the index of the newly-created row
* @throws IndexOutOfBoundsException
*/
@Override
public int insertRow(int beforeRow) {
// Physically insert the row
int index = super.insertRow(beforeRow);
numRows++;
// Add the columns to the new row
for (int i = 0; i < numColumns; i++) {
insertCell(index, i);
}
return index;
}
@Override
public void removeRow(int row) {
super.removeRow(row);
numRows--;
}
/**
* Resizes the grid.
*
* @param rows the number of rows
* @param columns the number of columns
* @throws IndexOutOfBoundsException
*/
public void resize(int rows, int columns) {
resizeColumns(columns);
resizeRows(rows);
}
/**
* Resizes the grid to the specified number of columns.
*
* @param columns the number of columns
* @throws IndexOutOfBoundsException
*/
public void resizeColumns(int columns) {
if (numColumns == columns) {
return;
}
if (columns < 0) {
throw new IndexOutOfBoundsException("Cannot set number of columns to "
+ columns);
}
if (numColumns > columns) {
// Fewer columns. Remove extraneous cells.
for (int i = 0; i < numRows; i++) {
for (int j = numColumns - 1; j >= columns; j--) {
removeCell(i, j);
}
}
} else {
// More columns. add cells where necessary.
for (int i = 0; i < numRows; i++) {
for (int j = numColumns; j < columns; j++) {
insertCell(i, j);
}
}
}
numColumns = columns;
// Update the size of the colgroup.
getColumnFormatter().resizeColumnGroup(columns, false);
}
/**
* Resizes the grid to the specified number of rows.
*
* @param rows the number of rows
* @throws IndexOutOfBoundsException
*/
public void resizeRows(int rows) {
if (numRows == rows) {
return;
}
if (rows < 0) {
throw new IndexOutOfBoundsException("Cannot set number of rows to "
+ rows);
}
if (numRows < rows) {
addRows(getBodyElement(), rows - numRows, numColumns);
numRows = rows;
} else {
while (numRows > rows) {
// Fewer rows. Remove extraneous ones.
removeRow(numRows - 1);
}
}
}
/**
* Creates a new, empty cell.
*/
@Override
protected Element createCell() {
Element td = super.createCell();
// Add a non-breaking space to the TD. This ensures that the cell is
// displayed.
DOM.setInnerHTML(td, " ");
return td;
}
/**
* Checks that a cell is a valid cell in the table.
*
* @param row the cell's row
* @param column the cell's column
* @throws IndexOutOfBoundsException
*/
@Override
protected void prepareCell(int row, int column) {
// Ensure that the indices are not negative.
prepareRow(row);
if (column < 0) {
throw new IndexOutOfBoundsException(
"Cannot access a column with a negative index: " + column);
}
if (column >= numColumns) {
throw new IndexOutOfBoundsException("Column index: " + column
+ ", Column size: " + numColumns);
}
}
/**
* Checks that the column index is valid.
*
* @param column The column index to be checked
* @throws IndexOutOfBoundsException if the column is negative
*/
@Override
protected void prepareColumn(int column) {
super.prepareColumn(column);
/**
* Grid does not lazily create cells, so simply ensure that the requested
* column and column are valid
*/
if (column >= numColumns) {
throw new IndexOutOfBoundsException("Column index: " + column
+ ", Column size: " + numColumns);
}
}
/**
* Checks that the row index is valid.
*
* @param row The row index to be checked
* @throws IndexOutOfBoundsException if the row is negative
*/
@Override
protected void prepareRow(int row) {
// Ensure that the indices are not negative.
if (row < 0) {
throw new IndexOutOfBoundsException(
"Cannot access a row with a negative index: " + row);
}
/**
* Grid does not lazily create cells, so simply ensure that the requested
* row and column are valid
*/
if (row >= numRows) {
throw new IndexOutOfBoundsException("Row index: " + row + ", Row size: "
+ numRows);
}
}
}