1b852bce914dc3ae05b26f3655bfb437ffed001bejamesrenpackage autotest.common.table; 2b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 3b852bce914dc3ae05b26f3655bfb437ffed001bejamesrenimport autotest.common.DomUtils; 4b852bce914dc3ae05b26f3655bfb437ffed001bejamesrenimport autotest.common.ui.RightClickTable; 5b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 6b852bce914dc3ae05b26f3655bfb437ffed001bejamesrenimport com.google.gwt.event.dom.client.ClickEvent; 7b852bce914dc3ae05b26f3655bfb437ffed001bejamesrenimport com.google.gwt.user.client.DOM; 8b852bce914dc3ae05b26f3655bfb437ffed001bejamesrenimport com.google.gwt.user.client.Element; 9b852bce914dc3ae05b26f3655bfb437ffed001bejamesrenimport com.google.gwt.user.client.Event; 10b852bce914dc3ae05b26f3655bfb437ffed001bejamesrenimport com.google.gwt.user.client.ui.HTMLTable; 11b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 12b852bce914dc3ae05b26f3655bfb437ffed001bejamesrenimport java.util.ArrayList; 13b852bce914dc3ae05b26f3655bfb437ffed001bejamesrenimport java.util.List; 14b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 15b852bce914dc3ae05b26f3655bfb437ffed001bejamesren/** 16b852bce914dc3ae05b26f3655bfb437ffed001bejamesren * Customized table class supporting multiple tbody elements. It is modified to support input 17b852bce914dc3ae05b26f3655bfb437ffed001bejamesren * handling, getRowCount(), getCellCount(), and getCellFormatter().getElement(). getElement() 18b852bce914dc3ae05b26f3655bfb437ffed001bejamesren * also works. Calls to other methods aren't guaranteed to work. 19b852bce914dc3ae05b26f3655bfb437ffed001bejamesren */ 20b852bce914dc3ae05b26f3655bfb437ffed001bejamesrenpublic class FragmentedTable extends RightClickTable { 21b852bce914dc3ae05b26f3655bfb437ffed001bejamesren public class FragmentedCellFormatter extends HTMLTable.CellFormatter { 22b852bce914dc3ae05b26f3655bfb437ffed001bejamesren @Override 23b852bce914dc3ae05b26f3655bfb437ffed001bejamesren public Element getElement(int row, int column) { 24b852bce914dc3ae05b26f3655bfb437ffed001bejamesren checkCellBounds(row, column); 25b852bce914dc3ae05b26f3655bfb437ffed001bejamesren Element bodyElem = bodyElems.get(getFragmentIndex(row)); 26b852bce914dc3ae05b26f3655bfb437ffed001bejamesren return getCellElement(bodyElem, getRowWithinFragment(row), column); 27b852bce914dc3ae05b26f3655bfb437ffed001bejamesren } 28b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 29b852bce914dc3ae05b26f3655bfb437ffed001bejamesren /** 30b852bce914dc3ae05b26f3655bfb437ffed001bejamesren * Native method to efficiently get a td element from a tbody. Copied from GWT's 31b852bce914dc3ae05b26f3655bfb437ffed001bejamesren * HTMLTable.java. 32b852bce914dc3ae05b26f3655bfb437ffed001bejamesren */ 33b852bce914dc3ae05b26f3655bfb437ffed001bejamesren private native Element getCellElement(Element tbody, int row, int col) /*-{ 34b852bce914dc3ae05b26f3655bfb437ffed001bejamesren return tbody.rows[row].cells[col]; 35b852bce914dc3ae05b26f3655bfb437ffed001bejamesren }-*/; 36b852bce914dc3ae05b26f3655bfb437ffed001bejamesren } 37b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 38b852bce914dc3ae05b26f3655bfb437ffed001bejamesren private List<Element> bodyElems = new ArrayList<Element>(); 39b852bce914dc3ae05b26f3655bfb437ffed001bejamesren private int totalRowCount; 40b852bce914dc3ae05b26f3655bfb437ffed001bejamesren private int rowsPerFragment; 41b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 42b852bce914dc3ae05b26f3655bfb437ffed001bejamesren public FragmentedTable() { 43b852bce914dc3ae05b26f3655bfb437ffed001bejamesren super(); 44b852bce914dc3ae05b26f3655bfb437ffed001bejamesren setCellFormatter(new FragmentedCellFormatter()); 45b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 46b852bce914dc3ae05b26f3655bfb437ffed001bejamesren // Reset the FragmentedTable to clear out elements that were added by the HTMLTable and 47b852bce914dc3ae05b26f3655bfb437ffed001bejamesren // FlexTable constructors 48b852bce914dc3ae05b26f3655bfb437ffed001bejamesren reset(); 49b852bce914dc3ae05b26f3655bfb437ffed001bejamesren } 50b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 51b852bce914dc3ae05b26f3655bfb437ffed001bejamesren /** 52b852bce914dc3ae05b26f3655bfb437ffed001bejamesren * This method must be called after added or removing tbody elements and before using other 53b852bce914dc3ae05b26f3655bfb437ffed001bejamesren * functionality (accessing cell elements, input handling, etc.). 54b852bce914dc3ae05b26f3655bfb437ffed001bejamesren */ 55b852bce914dc3ae05b26f3655bfb437ffed001bejamesren public void updateBodyElems() { 56b852bce914dc3ae05b26f3655bfb437ffed001bejamesren totalRowCount = 0; 57b852bce914dc3ae05b26f3655bfb437ffed001bejamesren Element tbody = DOM.getFirstChild(getElement()); 58b852bce914dc3ae05b26f3655bfb437ffed001bejamesren for(; tbody != null; tbody = DOM.getNextSibling(tbody)) { 59b852bce914dc3ae05b26f3655bfb437ffed001bejamesren assert tbody.getTagName().equalsIgnoreCase("tbody"); 60b852bce914dc3ae05b26f3655bfb437ffed001bejamesren bodyElems.add(tbody); 61b852bce914dc3ae05b26f3655bfb437ffed001bejamesren totalRowCount += getRowCount(tbody); 62b852bce914dc3ae05b26f3655bfb437ffed001bejamesren } 63b852bce914dc3ae05b26f3655bfb437ffed001bejamesren } 64b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 65b852bce914dc3ae05b26f3655bfb437ffed001bejamesren public void reset() { 66b852bce914dc3ae05b26f3655bfb437ffed001bejamesren bodyElems.clear(); 67b852bce914dc3ae05b26f3655bfb437ffed001bejamesren DomUtils.clearDomChildren(getElement()); 68b852bce914dc3ae05b26f3655bfb437ffed001bejamesren } 69b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 70b852bce914dc3ae05b26f3655bfb437ffed001bejamesren private int getRowWithinFragment(int row) { 71b852bce914dc3ae05b26f3655bfb437ffed001bejamesren return row % rowsPerFragment; 72b852bce914dc3ae05b26f3655bfb437ffed001bejamesren } 73b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 74b852bce914dc3ae05b26f3655bfb437ffed001bejamesren private int getFragmentIndex(int row) { 75b852bce914dc3ae05b26f3655bfb437ffed001bejamesren return row / rowsPerFragment; 76b852bce914dc3ae05b26f3655bfb437ffed001bejamesren } 77b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 78b852bce914dc3ae05b26f3655bfb437ffed001bejamesren @Override 79b852bce914dc3ae05b26f3655bfb437ffed001bejamesren public HTMLTable.Cell getCellForEvent(ClickEvent event) { 80b852bce914dc3ae05b26f3655bfb437ffed001bejamesren return getCellForDomEvent(event); 81b852bce914dc3ae05b26f3655bfb437ffed001bejamesren } 82b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 83b852bce914dc3ae05b26f3655bfb437ffed001bejamesren @Override 84b852bce914dc3ae05b26f3655bfb437ffed001bejamesren protected RowColumn getCellPosition(Element td) { 85b852bce914dc3ae05b26f3655bfb437ffed001bejamesren Element tr = DOM.getParent(td); 86b852bce914dc3ae05b26f3655bfb437ffed001bejamesren Element body = DOM.getParent(tr); 87b852bce914dc3ae05b26f3655bfb437ffed001bejamesren int fragmentIndex = DOM.getChildIndex(getElement(), body); 88b852bce914dc3ae05b26f3655bfb437ffed001bejamesren int rowWithinFragment = DOM.getChildIndex(body, tr); 89b852bce914dc3ae05b26f3655bfb437ffed001bejamesren int row = fragmentIndex * rowsPerFragment + rowWithinFragment; 90b852bce914dc3ae05b26f3655bfb437ffed001bejamesren int column = DOM.getChildIndex(tr, td); 91b852bce914dc3ae05b26f3655bfb437ffed001bejamesren return new RowColumn(row, column); 92b852bce914dc3ae05b26f3655bfb437ffed001bejamesren } 93b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 94b852bce914dc3ae05b26f3655bfb437ffed001bejamesren /** 95b852bce914dc3ae05b26f3655bfb437ffed001bejamesren * This is a modified version of getEventTargetCell() from HTMLTable.java. 96b852bce914dc3ae05b26f3655bfb437ffed001bejamesren */ 97b852bce914dc3ae05b26f3655bfb437ffed001bejamesren @Override 98b852bce914dc3ae05b26f3655bfb437ffed001bejamesren protected Element getEventTargetCell(Event event) { 99b852bce914dc3ae05b26f3655bfb437ffed001bejamesren Element td = DOM.eventGetTarget(event); 100b852bce914dc3ae05b26f3655bfb437ffed001bejamesren for (; td != null; td = DOM.getParent(td)) { 101b852bce914dc3ae05b26f3655bfb437ffed001bejamesren // If it's a TD, it might be the one we're looking for. 102b852bce914dc3ae05b26f3655bfb437ffed001bejamesren if (DOM.getElementProperty(td, "tagName").equalsIgnoreCase("td")) { 103b852bce914dc3ae05b26f3655bfb437ffed001bejamesren // Make sure it's directly a part of this table before returning 104b852bce914dc3ae05b26f3655bfb437ffed001bejamesren // it. 105b852bce914dc3ae05b26f3655bfb437ffed001bejamesren Element tr = DOM.getParent(td); 106b852bce914dc3ae05b26f3655bfb437ffed001bejamesren Element body = DOM.getParent(tr); 107b852bce914dc3ae05b26f3655bfb437ffed001bejamesren Element tableElem = DOM.getParent(body); 108b852bce914dc3ae05b26f3655bfb437ffed001bejamesren if (tableElem == getElement()) { 109b852bce914dc3ae05b26f3655bfb437ffed001bejamesren return td; 110b852bce914dc3ae05b26f3655bfb437ffed001bejamesren } 111b852bce914dc3ae05b26f3655bfb437ffed001bejamesren } 112b852bce914dc3ae05b26f3655bfb437ffed001bejamesren // If we run into this table's element, we're out of options. 113b852bce914dc3ae05b26f3655bfb437ffed001bejamesren if (td == getElement()) { 114b852bce914dc3ae05b26f3655bfb437ffed001bejamesren return null; 115b852bce914dc3ae05b26f3655bfb437ffed001bejamesren } 116b852bce914dc3ae05b26f3655bfb437ffed001bejamesren } 117b852bce914dc3ae05b26f3655bfb437ffed001bejamesren return null; 118b852bce914dc3ae05b26f3655bfb437ffed001bejamesren } 119b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 120b852bce914dc3ae05b26f3655bfb437ffed001bejamesren @Override 121b852bce914dc3ae05b26f3655bfb437ffed001bejamesren public int getCellCount(int row) { 122b852bce914dc3ae05b26f3655bfb437ffed001bejamesren Element bodyElem = bodyElems.get(getFragmentIndex(row)); 123b852bce914dc3ae05b26f3655bfb437ffed001bejamesren return getCellCount(bodyElem, getRowWithinFragment(row)); 124b852bce914dc3ae05b26f3655bfb437ffed001bejamesren } 125b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 126b852bce914dc3ae05b26f3655bfb437ffed001bejamesren @Override 127b852bce914dc3ae05b26f3655bfb437ffed001bejamesren public int getRowCount() { 128b852bce914dc3ae05b26f3655bfb437ffed001bejamesren return totalRowCount; 129b852bce914dc3ae05b26f3655bfb437ffed001bejamesren } 130b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 131b852bce914dc3ae05b26f3655bfb437ffed001bejamesren private native int getRowCount(Element tbody) /*-{ 132b852bce914dc3ae05b26f3655bfb437ffed001bejamesren return tbody.rows.length; 133b852bce914dc3ae05b26f3655bfb437ffed001bejamesren }-*/; 134b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 135b852bce914dc3ae05b26f3655bfb437ffed001bejamesren private native int getCellCount(Element tbody, int row) /*-{ 136b852bce914dc3ae05b26f3655bfb437ffed001bejamesren return tbody.rows[row].cells.length; 137b852bce914dc3ae05b26f3655bfb437ffed001bejamesren }-*/; 138b852bce914dc3ae05b26f3655bfb437ffed001bejamesren 139b852bce914dc3ae05b26f3655bfb437ffed001bejamesren /** 140b852bce914dc3ae05b26f3655bfb437ffed001bejamesren * This must be called before using other functionality (accessing cell elements, input 141b852bce914dc3ae05b26f3655bfb437ffed001bejamesren * handling, etc.). 142b852bce914dc3ae05b26f3655bfb437ffed001bejamesren * @param rowsPerFragment The number of rows in each tbody. The last tbody may have fewer 143b852bce914dc3ae05b26f3655bfb437ffed001bejamesren * rows. All others must have exactly this number of rows. 144b852bce914dc3ae05b26f3655bfb437ffed001bejamesren */ 145b852bce914dc3ae05b26f3655bfb437ffed001bejamesren public void setRowsPerFragment(int rowsPerFragment) { 146b852bce914dc3ae05b26f3655bfb437ffed001bejamesren this.rowsPerFragment = rowsPerFragment; 147b852bce914dc3ae05b26f3655bfb437ffed001bejamesren } 148b852bce914dc3ae05b26f3655bfb437ffed001bejamesren} 149