blob: 53a30b3cbdc83ec24123dba807825d62d2d93411 [file] [log] [blame]
package autotest.common.table;
import autotest.common.DomUtils;
import autotest.common.ui.RightClickTable;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.HTMLTable;
import java.util.ArrayList;
import java.util.List;
/**
* Customized table class supporting multiple tbody elements. It is modified to support input
* handling, getRowCount(), getCellCount(), and getCellFormatter().getElement(). getElement()
* also works. Calls to other methods aren't guaranteed to work.
*/
public class FragmentedTable extends RightClickTable {
public class FragmentedCellFormatter extends HTMLTable.CellFormatter {
@Override
public Element getElement(int row, int column) {
checkCellBounds(row, column);
Element bodyElem = bodyElems.get(getFragmentIndex(row));
return getCellElement(bodyElem, getRowWithinFragment(row), column);
}
/**
* Native method to efficiently get a td element from a tbody. Copied from GWT's
* HTMLTable.java.
*/
private native Element getCellElement(Element tbody, int row, int col) /*-{
return tbody.rows[row].cells[col];
}-*/;
}
private List<Element> bodyElems = new ArrayList<Element>();
private int totalRowCount;
private int rowsPerFragment;
public FragmentedTable() {
super();
setCellFormatter(new FragmentedCellFormatter());
// Reset the FragmentedTable to clear out elements that were added by the HTMLTable and
// FlexTable constructors
reset();
}
/**
* This method must be called after added or removing tbody elements and before using other
* functionality (accessing cell elements, input handling, etc.).
*/
public void updateBodyElems() {
totalRowCount = 0;
Element tbody = DOM.getFirstChild(getElement());
for(; tbody != null; tbody = DOM.getNextSibling(tbody)) {
assert tbody.getTagName().equalsIgnoreCase("tbody");
bodyElems.add(tbody);
totalRowCount += getRowCount(tbody);
}
}
public void reset() {
bodyElems.clear();
DomUtils.clearDomChildren(getElement());
}
private int getRowWithinFragment(int row) {
return row % rowsPerFragment;
}
private int getFragmentIndex(int row) {
return row / rowsPerFragment;
}
@Override
public HTMLTable.Cell getCellForEvent(ClickEvent event) {
return getCellForDomEvent(event);
}
@Override
protected RowColumn getCellPosition(Element td) {
Element tr = DOM.getParent(td);
Element body = DOM.getParent(tr);
int fragmentIndex = DOM.getChildIndex(getElement(), body);
int rowWithinFragment = DOM.getChildIndex(body, tr);
int row = fragmentIndex * rowsPerFragment + rowWithinFragment;
int column = DOM.getChildIndex(tr, td);
return new RowColumn(row, column);
}
/**
* This is a modified version of getEventTargetCell() from HTMLTable.java.
*/
@Override
protected Element getEventTargetCell(Event event) {
Element td = DOM.eventGetTarget(event);
for (; td != null; td = DOM.getParent(td)) {
// If it's a TD, it might be the one we're looking for.
if (DOM.getElementProperty(td, "tagName").equalsIgnoreCase("td")) {
// Make sure it's directly a part of this table before returning
// it.
Element tr = DOM.getParent(td);
Element body = DOM.getParent(tr);
Element tableElem = DOM.getParent(body);
if (tableElem == getElement()) {
return td;
}
}
// If we run into this table's element, we're out of options.
if (td == getElement()) {
return null;
}
}
return null;
}
@Override
public int getCellCount(int row) {
Element bodyElem = bodyElems.get(getFragmentIndex(row));
return getCellCount(bodyElem, getRowWithinFragment(row));
}
@Override
public int getRowCount() {
return totalRowCount;
}
private native int getRowCount(Element tbody) /*-{
return tbody.rows.length;
}-*/;
private native int getCellCount(Element tbody, int row) /*-{
return tbody.rows[row].cells.length;
}-*/;
/**
* This must be called before using other functionality (accessing cell elements, input
* handling, etc.).
* @param rowsPerFragment The number of rows in each tbody. The last tbody may have fewer
* rows. All others must have exactly this number of rows.
*/
public void setRowsPerFragment(int rowsPerFragment) {
this.rowsPerFragment = rowsPerFragment;
}
}