Java tutorial
/* * Copyright 2013 JBoss 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 org.overlord.commons.gwt.client.local.widgets; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Node; import com.google.gwt.dom.client.NodeList; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.Widget; /** * A table implementation that can have arbitrary widgets in the cells. * * @author eric.wittmann@redhat.com */ public class WidgetTable extends Panel { protected List<Widget> children = new ArrayList<Widget>(); /** Map of widget to td element. */ protected Map<Widget, Element> wrapperMap = new HashMap<Widget, Element>(); protected int columnCount; protected Element thead; protected Element tbody; protected List<Element> rowElements = new ArrayList<Element>(); /** Extra class information for the data column TD's. */ protected Map<Integer, String> columnClasses = new HashMap<Integer, String>(); /** * Constructor. */ public WidgetTable() { setElement(Document.get().createTableElement()); init(); } /** * Init the thead and tbody. */ protected void init() { thead = Document.get().createTHeadElement().cast(); tbody = Document.get().createTBodyElement().cast(); DOM.appendChild(getElement(), thead); DOM.appendChild(getElement(), tbody); } /** * Creates the thead and th elements, with the given labels. * @param labels */ public void setColumnLabels(String... labels) { this.columnCount = labels.length; for (String label : labels) { Element thElement = Document.get().createTHElement().cast(); thElement.setInnerText(label); DOM.appendChild(thead, thElement); } } /** * @see com.google.gwt.user.client.ui.Panel#add(com.google.gwt.user.client.ui.Widget) */ @Override public void add(Widget widget) { throw new RuntimeException("Method not supported. Try another variant of add()."); //$NON-NLS-1$ } /** * Adds a single widget to the table, at the right row and column. * * @param rowIndex which row to add to (0 based, excluding thead) * @param colIndex which column to add to (0 based) * @param widget the widget to add to the table */ public Element add(int rowIndex, int colIndex, Widget widget) { if (widget == null) throw new NullPointerException("Cannot add a null widget."); //$NON-NLS-1$ if (colIndex >= this.columnCount || colIndex < 0) throw new IndexOutOfBoundsException("Requested column index is out of range."); //$NON-NLS-1$ Element tr = ensureRow(rowIndex); Element td = ensureCell(tr, colIndex); widget.removeFromParent(); children.add(widget); wrapperMap.put(widget, td); DOM.appendChild(td, widget.getElement()); adopt(widget); return td; } /** * Remove a single row and all its widgets from the table * * @param rowIndex which row to add to (0 based, excluding thead) */ public void deleteRow(int rowIndex) { Element rowElem = rowElements.get(rowIndex); NodeList<Node> tds = rowElem.getChildNodes(); for (int i = 0; i < tds.getLength(); i++) { Element td = tds.getItem(i).cast(); for (Widget widget : wrapperMap.keySet()) { if (wrapperMap.get(widget).equals(td)) { remove(widget); break; } } } this.tbody.removeChild(rowElem); rowElements.remove(rowIndex); } /** * Gets the row element at a given index. * @param rowIndex */ public Element getRow(int rowIndex) { return ensureRow(rowIndex); } /** * Ensures that a row at the given index exists. * @param rowIndex */ private Element ensureRow(int rowIndex) { NodeList<Node> childNodes = this.tbody.getChildNodes(); int numTRs = childNodes.getLength(); if (rowIndex < numTRs) { return childNodes.getItem(rowIndex).cast(); } Element tr = null; for (int r = numTRs; r <= rowIndex; r++) { tr = Document.get().createTRElement().cast(); DOM.appendChild(this.tbody, tr); this.rowElements.add(tr); } return tr; } /** * Ensure that a td cell exists for the row at the given column * index. * @param tr the row * @param colIndex the column index (0 based) * @return the new or already existing td */ private Element ensureCell(Element tr, int colIndex) { NodeList<Node> tds = tr.getChildNodes(); int numTDs = tds.getLength(); if (colIndex < numTDs) { return tds.getItem(colIndex).cast(); } Element td = null; for (int c = numTDs; c <= colIndex; c++) { td = Document.get().createTDElement().cast(); if (this.columnClasses.containsKey(colIndex)) { td.setAttribute("class", this.columnClasses.get(colIndex)); //$NON-NLS-1$ } DOM.appendChild(tr, td); } return td; } /** * @see com.google.gwt.user.client.ui.Panel#clear() */ @Override public void clear() { List<Widget> childrenClone = new ArrayList<Widget>(this.children); for (Widget widget : childrenClone) { this.remove(widget); } for (Element rowElem : this.rowElements) { this.tbody.removeChild(rowElem); } this.rowElements.clear(); } /** * @see com.google.gwt.user.client.ui.HasWidgets#iterator() */ @Override public Iterator<Widget> iterator() { return this.children.iterator(); } /** * @see com.google.gwt.user.client.ui.Panel#remove(com.google.gwt.user.client.ui.Widget) */ @Override public boolean remove(Widget w) { if (!this.children.contains(w)) return false; orphan(w); Element tdWrapper = this.wrapperMap.get(w); tdWrapper.getParentElement().removeChild(tdWrapper); this.children.remove(w); this.wrapperMap.remove(w); return true; } /** * @return the number of rows (not including the thead) in the table */ public int getRowCount() { return this.rowElements.size(); } /** * Add extra class information that will be added to the TD for all data * rows (at the given column index). * @param columnIndex 0 based column index * @param classes additional html class information */ public void setColumnClasses(int columnIndex, String classes) { this.columnClasses.put(columnIndex, classes); } }