/*
 * Copyright 2007 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.core.client.JsArray;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.TableCellElement;
import com.google.gwt.dom.client.TableRowElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.DoubleClickEvent;
import com.google.gwt.event.dom.client.DoubleClickHandler;
import com.google.gwt.event.dom.client.DragEndEvent;
import com.google.gwt.event.dom.client.DragEndHandler;
import com.google.gwt.event.dom.client.DragEnterEvent;
import com.google.gwt.event.dom.client.DragEnterHandler;
import com.google.gwt.event.dom.client.DragEvent;
import com.google.gwt.event.dom.client.DragHandler;
import com.google.gwt.event.dom.client.DragLeaveEvent;
import com.google.gwt.event.dom.client.DragLeaveHandler;
import com.google.gwt.event.dom.client.DragOverEvent;
import com.google.gwt.event.dom.client.DragOverHandler;
import com.google.gwt.event.dom.client.DragStartEvent;
import com.google.gwt.event.dom.client.DragStartHandler;
import com.google.gwt.event.dom.client.DropEvent;
import com.google.gwt.event.dom.client.DropHandler;
import com.google.gwt.event.dom.client.HasAllDragAndDropHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasDoubleClickHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.annotations.IsSafeHtml;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.impl.ElementMapperImpl;
import com.google.gwt.user.client.ui.HasHorizontalAlignment.HorizontalAlignmentConstant;
import com.google.gwt.user.client.ui.HasVerticalAlignment.VerticalAlignmentConstant;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * HTMLTable contains the common table algorithms for
 * {@link com.google.gwt.user.client.ui.Grid} and
 * {@link com.google.gwt.user.client.ui.FlexTable}.
 * <p>
 * <img class='gallery' src='doc-files/Table.png'/>
 * </p>
 */
@SuppressWarnings("deprecation")
public abstract class HTMLTable extends Panel implements SourcesTableEvents,
    HasAllDragAndDropHandlers, HasClickHandlers, HasDoubleClickHandlers {

  /**
   * Interface to access {@link HTMLTable}'s DOM.
   */
  private interface HTMLTableImpl {
    JsArray<Element> getRows(Element tbody);

    JsArray<Element> getCells(Element row);
  }

  /**
   * Standard implementation for accessing the Table DOM.
   */
  @SuppressWarnings("unused") // used due to rebinding
  private static class HTMLTableStandardImpl implements HTMLTableImpl {

    @Override
    public native JsArray<Element> getRows(Element tbody) /*-{
      return tbody.rows;
    }-*/;

    @Override
    public native JsArray<Element> getCells(Element row) /*-{
      return row.cells;
    }-*/;
  }

  /**
   * IE specific implementation for accessing the Table DOM.
   * see: issue 6938
   */
  @SuppressWarnings("unused") // used due to rebinding
  private static class HTMLTableIEImpl implements HTMLTableImpl {

    @Override
    public native JsArray<Element> getRows(Element tbody) /*-{
      return tbody.children;
    }-*/;

    @Override
    public native JsArray<Element> getCells(Element row) /*-{
      return row.children;
    }-*/;
  }

  /**
   * Return value for {@link HTMLTable#getCellForEvent}.
   */
  public class Cell {
    private final int rowIndex;
    private final int cellIndex;

    /**
     * Creates a cell.
     * 
     * @param rowIndex the cell's row
     * @param cellIndex the cell's index
     */
    protected Cell(int rowIndex, int cellIndex) {
      this.cellIndex = cellIndex;
      this.rowIndex = rowIndex;
    }

    /**
     * Gets the cell index.
     * 
     * @return the cell index
     */
    public int getCellIndex() {
      return cellIndex;
    }

    /**
     * Gets the cell's element.
     * 
     * @return the cell's element.
     */
    public com.google.gwt.user.client.Element getElement() {
      return DOM.asOld(getCellFormatter().getElement(rowIndex, cellIndex));
    }

    /**
     * Get row index.
     * 
     * @return the row index
     */
    public int getRowIndex() {
      return rowIndex;
    }
  }
  /**
   * This class contains methods used to format a table's cells.
   */
  public class CellFormatter {
    /**
     * Adds a style to the specified cell.
     * 
     * @param row the cell's row
     * @param column the cell's column
     * @param styleName the style name to be added
     * @see UIObject#addStyleName(String)
     */
    public void addStyleName(int row, int column, String styleName) {
      prepareCell(row, column);
      Element td = getCellElement(bodyElem, row, column);
      UIObject.setStyleName(td, styleName, true);
    }

    /**
     * Gets the TD element representing the specified cell.
     * 
     * @param row the row of the cell to be retrieved
     * @param column the column of the cell to be retrieved
     * @return the column's TD element
     * @throws IndexOutOfBoundsException
     */
    public com.google.gwt.user.client.Element getElement(int row, int column) {
      checkCellBounds(row, column);
      return DOM.asOld(getCellElement(bodyElem, row, column));
    }

    /**
     * Gets the style of a specified cell.
     * 
     * @param row the cell's row
     * @param column the cell's column
     * @see UIObject#getStyleName()
     * @return returns the style name
     * @throws IndexOutOfBoundsException
     */
    public String getStyleName(int row, int column) {
      return UIObject.getStyleName(getElement(row, column));
    }

    /**
     * Gets the primary style of a specified cell.
     * 
     * @param row the cell's row
     * @param column the cell's column
     * @see UIObject#getStylePrimaryName()
     * @return returns the style name
     * @throws IndexOutOfBoundsException
     */
    public String getStylePrimaryName(int row, int column) {
      return UIObject.getStylePrimaryName(getElement(row, column));
    }

    /**
     * Determines whether or not this cell is visible.
     * 
     * @param row the row of the cell whose visibility is to be set
     * @param column the column of the cell whose visibility is to be set
     * @return <code>true</code> if the object is visible
     */
    public boolean isVisible(int row, int column) {
      Element e = getElement(row, column);
      return UIObject.isVisible(e);
    }

    /**
     * Removes a style from the specified cell.
     * 
     * @param row the cell's row
     * @param column the cell's column
     * @param styleName the style name to be removed
     * @see UIObject#removeStyleName(String)
     * @throws IndexOutOfBoundsException
     */
    public void removeStyleName(int row, int column, String styleName) {
      checkCellBounds(row, column);
      Element td = getCellElement(bodyElem, row, column);
      UIObject.setStyleName(td, styleName, false);
    }

    /**
     * Sets the horizontal and vertical alignment of the specified cell's
     * contents.
     * 
     * @param row the row of the cell whose alignment is to be set
     * @param column the column of the cell whose alignment is to be set
     * @param hAlign the cell's new horizontal alignment as specified in
     *          {@link HasHorizontalAlignment}
     * @param vAlign the cell's new vertical alignment as specified in
     *          {@link HasVerticalAlignment}
     * @throws IndexOutOfBoundsException
     */
    public void setAlignment(int row, int column,
        HorizontalAlignmentConstant hAlign, VerticalAlignmentConstant vAlign) {
      setHorizontalAlignment(row, column, hAlign);
      setVerticalAlignment(row, column, vAlign);
    }

    /**
     * Sets the height of the specified cell.
     * 
     * @param row the row of the cell whose height is to be set
     * @param column the column of the cell whose height is to be set
     * @param height the cell's new height, in CSS units
     * @throws IndexOutOfBoundsException
     */
    public void setHeight(int row, int column, String height) {
      prepareCell(row, column);
      Element elem = getCellElement(bodyElem, row, column);
      elem.setPropertyString("height", height);
    }

    /**
     * Sets the horizontal alignment of the specified cell.
     * 
     * @param row the row of the cell whose alignment is to be set
     * @param column the column of the cell whose alignment is to be set
     * @param align the cell's new horizontal alignment as specified in
     *          {@link HasHorizontalAlignment}.
     * @throws IndexOutOfBoundsException
     */
    public void setHorizontalAlignment(int row, int column,
        HorizontalAlignmentConstant align) {
      prepareCell(row, column);
      Element elem = getCellElement(bodyElem, row, column);
      elem.setPropertyString("align", align.getTextAlignString());
    }

    /**
     * Sets the style name associated with the specified cell.
     *
     * @param row the row of the cell whose style name is to be set
     * @param column the column of the cell whose style name is to be set
     * @param styleName the new style name
     * @see UIObject#setStyleName(String)
     * @throws IndexOutOfBoundsException
     */
    public void setStyleName(int row, int column, String styleName) {
      prepareCell(row, column);
      UIObject.setStyleName(getCellElement(bodyElem, row, column), styleName);
    }

    /**
     * Sets the primary style name associated with the specified cell.
     * 
     * @param row the row of the cell whose style name is to be set
     * @param column the column of the cell whose style name is to be set
     * @param styleName the new style name
     * @see UIObject#setStylePrimaryName(String)
     * @throws IndexOutOfBoundsException
     */
    public void setStylePrimaryName(int row, int column, String styleName) {
      UIObject.setStylePrimaryName(getCellElement(bodyElem, row, column),
          styleName);
    }

    /**
     * Sets the vertical alignment of the specified cell.
     * 
     * @param row the row of the cell whose alignment is to be set
     * @param column the column of the cell whose alignment is to be set
     * @param align the cell's new vertical alignment as specified in
     *          {@link HasVerticalAlignment}.
     * @throws IndexOutOfBoundsException
     */
    public void setVerticalAlignment(int row, int column,
        VerticalAlignmentConstant align) {
      prepareCell(row, column);
      getCellElement(bodyElem, row, column).getStyle()
          .setProperty("verticalAlign", align.getVerticalAlignString());
    }

    /**
     * Sets whether this cell is visible via the display style property. The
     * other cells in the row will all shift left to fill the cell's space. So,
     * for example a table with (0,1,2) will become (1,2) if cell 1 is hidden.
     * 
     * @param row the row of the cell whose visibility is to be set
     * @param column the column of the cell whose visibility is to be set
     * @param visible <code>true</code> to show the cell, <code>false</code> to
     *          hide it
     */
    public void setVisible(int row, int column, boolean visible) {
      Element e = ensureElement(row, column);
      UIObject.setVisible(e, visible);
    }

    /**
     * Sets the width of the specified cell.
     * 
     * @param row the row of the cell whose width is to be set
     * @param column the column of the cell whose width is to be set
     * @param width the cell's new width, in CSS units
     * @throws IndexOutOfBoundsException
     */
    public void setWidth(int row, int column, String width) {
      // Give the subclass a chance to prepare the cell.
      prepareCell(row, column);
      getCellElement(bodyElem, row, column).setPropertyString("width", width);
    }

    /**
     * Sets whether the specified cell will allow word wrapping of its contents.
     * 
     * @param row the row of the cell whose word-wrap is to be set
     * @param column the column of the cell whose word-wrap is to be set
     * @param wrap <code>false </code> to disable word wrapping in this cell
     * @throws IndexOutOfBoundsException
     */
    public void setWordWrap(int row, int column, boolean wrap) {
      prepareCell(row, column);
      String wrapValue = wrap ? "" : "nowrap";
      getElement(row, column).getStyle().setProperty("whiteSpace", wrapValue);
    }

    /**
     * Gets the element associated with a cell. If it does not exist and the
     * subtype allows creation of elements, creates it.
     * 
     * @param row the cell's row
     * @param column the cell's column
     * @return the cell's element
     * @throws IndexOutOfBoundsException
     */
    protected com.google.gwt.user.client.Element ensureElement(int row, int column) {
      prepareCell(row, column);
      return DOM.asOld(getCellElement(bodyElem, row, column));
    }

    /**
     * Convenience methods to get an attribute on a cell.
     * 
     * @param row cell's row
     * @param column cell's column
     * @param attr attribute to get
     * @return the attribute's value
     * @throws IndexOutOfBoundsException
     */
    protected String getAttr(int row, int column, String attr) {
      Element elem = getElement(row, column);
      return elem.getAttribute(attr);
    }

    /**
     * Convenience methods to set an attribute on a cell.
     * 
     * @param row cell's row
     * @param column cell's column
     * @param attrName attribute to set
     * @param value value to set
     * @throws IndexOutOfBoundsException
     */
    protected void setAttr(int row, int column, String attrName, String value) {
      Element elem = ensureElement(row, column);
      elem.setAttribute(attrName, value);
    }

    /**
     * Get a cell's element.
     * 
     * @param tbody the table element
     * @param row the row of the cell
     * @param col the column of the cell
     * @return the element
     */
    private Element getCellElement(Element tbody, int row, int col) {
      return impl.getCells(impl.getRows(tbody).get(row)).get(col);
    }

    /**
     * Gets the TD element representing the specified cell unsafely (meaning
     * that it doesn't ensure that <code>row</code> and <code>column</code> are
     * valid).
     * 
     * @param row the row of the cell to be retrieved
     * @param column the column of the cell to be retrieved
     * @return the cell's TD element
     */
    private Element getRawElement(int row, int column) {
      return getCellElement(bodyElem, row, column);
    }
  }

  /**
   * This class contains methods used to format a table's columns. It is limited
   * by the support cross-browser HTML support for column formatting.
   */
  public class ColumnFormatter {
    protected Element columnGroup;

    /**
     * Adds a style to the specified column.
     * 
     * @param col the col to which the style will be added
     * @param styleName the style name to be added
     * @see UIObject#addStyleName(String)
     * @throws IndexOutOfBoundsException
     */
    public void addStyleName(int col, String styleName) {
      UIObject.setStyleName(ensureColumn(col), styleName, true);
    }

    /**
     * Get the col element for the column.
     * 
     * @param column the column index
     * @return the col element
     */
    public com.google.gwt.user.client.Element getElement(int column) {
      return DOM.asOld(ensureColumn(column));
    }

    /**
     * Gets the style of the specified column.
     * 
     * @param column the column to be queried
     * @return the style name
     * @see UIObject#getStyleName()
     * @throws IndexOutOfBoundsException
     */
    public String getStyleName(int column) {
      return UIObject.getStyleName(ensureColumn(column));
    }

    /**
     * Gets the primary style of the specified column.
     * 
     * @param column the column to be queried
     * @return the style name
     * @see UIObject#getStylePrimaryName()
     * @throws IndexOutOfBoundsException
     */
    public String getStylePrimaryName(int column) {
      return UIObject.getStylePrimaryName(ensureColumn(column));
    }

    /**
     * Removes a style from the specified column.
     * 
     * @param column the column from which the style will be removed
     * @param styleName the style name to be removed
     * @see UIObject#removeStyleName(String)
     * @throws IndexOutOfBoundsException
     */
    public void removeStyleName(int column, String styleName) {
      UIObject.setStyleName(ensureColumn(column), styleName, false);
    }

    /**
     * Sets the style name associated with the specified column.
     * 
     * @param column the column whose style name is to be set
     * @param styleName the new style name
     * @see UIObject#setStyleName(String)
     * @throws IndexOutOfBoundsException
     */
    public void setStyleName(int column, String styleName) {
      UIObject.setStyleName(ensureColumn(column), styleName);
    }

    /**
     * Sets the primary style name associated with the specified column.
     * 
     * @param column the column whose style name is to be set
     * @param styleName the new style name
     * @see UIObject#setStylePrimaryName(String)
     * @throws IndexOutOfBoundsException
     */
    public void setStylePrimaryName(int column, String styleName) {
      UIObject.setStylePrimaryName(ensureColumn(column), styleName);
    }

    /**
     * Sets the width of the specified column.
     * 
     * @param column the column of the cell whose width is to be set
     * @param width the cell's new width, in percentage or pixel units
     * @throws IndexOutOfBoundsException
     */
    public void setWidth(int column, String width) {
      ensureColumn(column).setPropertyString("width", width);
    }

    /**
     * Resize the column group element.
     * 
     * @param columns the number of columns
     * @param growOnly true to only grow, false to shrink if needed
     */
    void resizeColumnGroup(int columns, boolean growOnly) {
      // The colgroup should always have at least one element.  See
      // prepareColumnGroup() for more details.
      columns = Math.max(columns, 1);

      int num = columnGroup.getChildCount();
      if (num < columns) {
        for (int i = num; i < columns; i++) {
          columnGroup.appendChild(Document.get().createColElement());
        }
      } else if (!growOnly && num > columns) {
        for (int i = num; i > columns; i--) {
          columnGroup.removeChild(columnGroup.getLastChild());
        }
      }
    }

    private Element ensureColumn(int col) {
      prepareColumn(col);
      prepareColumnGroup();
      resizeColumnGroup(col + 1, true);
      return columnGroup.getChild(col).cast();
    }

    /**
     * Prepare the colgroup tag for the first time, guaranteeing that it exists
     * and has at least one col tag in it. This method corrects a Mozilla issue
     * where the col tag will affect the wrong column if a col tag doesn't exist
     * when the element is attached to the page.
     */
    private void prepareColumnGroup() {
      if (columnGroup == null) {
        columnGroup = DOM.createElement("colgroup");
        DOM.insertChild(tableElem, columnGroup, 0);
        DOM.appendChild(columnGroup, DOM.createElement("col"));
      }
    }
  }

  /**
   * This class contains methods used to format a table's rows.
   */
  public class RowFormatter {

    /**
     * Adds a style to the specified row.
     * 
     * @param row the row to which the style will be added
     * @param styleName the style name to be added
     * @see UIObject#addStyleName(String)
     * @throws IndexOutOfBoundsException
     */
    public void addStyleName(int row, String styleName) {
      UIObject.setStyleName(ensureElement(row), styleName, true);
    }

    /**
     * Gets the TR element representing the specified row.
     * 
     * @param row the row whose TR element is to be retrieved
     * @return the row's TR element
     * @throws IndexOutOfBoundsException
     */
    public com.google.gwt.user.client.Element getElement(int row) {
      checkRowBounds(row);
      return DOM.asOld(getRow(bodyElem, row));
    }

    /**
     * Gets the style of the specified row.
     * 
     * @param row the row to be queried
     * @return the style name
     * @see UIObject#getStyleName()
     * @throws IndexOutOfBoundsException
     */
    public String getStyleName(int row) {
      return UIObject.getStyleName(getElement(row));
    }

    /**
     * Gets the primary style of the specified row.
     * 
     * @param row the row to be queried
     * @return the style name
     * @see UIObject#getStylePrimaryName()
     * @throws IndexOutOfBoundsException
     */
    public String getStylePrimaryName(int row) {
      return UIObject.getStylePrimaryName(getElement(row));
    }

    /**
     * Determines whether or not this row is visible via the display style
     * attribute.
     * 
     * @param row the row whose visibility is to be set
     * @return <code>true</code> if the row is visible
     */
    public boolean isVisible(int row) {
      Element e = getElement(row);
      return UIObject.isVisible(e);
    }

    /**
     * Removes a style from the specified row.
     * 
     * @param row the row from which the style will be removed
     * @param styleName the style name to be removed
     * @see UIObject#removeStyleName(String)
     * @throws IndexOutOfBoundsException
     */
    public void removeStyleName(int row, String styleName) {
      UIObject.setStyleName(ensureElement(row), styleName, false);
    }

    /**
     * Sets the style name associated with the specified row.
     * 
     * @param row the row whose style name is to be set
     * @param styleName the new style name
     * @see UIObject#setStyleName(String)
     * @throws IndexOutOfBoundsException
     */
    public void setStyleName(int row, String styleName) {
      UIObject.setStyleName(ensureElement(row), styleName);
    }

    /**
     * Sets the primary style name associated with the specified row.
     * 
     * @param row the row whose style name is to be set
     * @param styleName the new style name
     * @see UIObject#setStylePrimaryName(String)
     * @throws IndexOutOfBoundsException
     */
    public void setStylePrimaryName(int row, String styleName) {
      UIObject.setStylePrimaryName(ensureElement(row), styleName);
    }

    /**
     * Sets the vertical alignment of the specified row.
     * 
     * @param row the row whose alignment is to be set
     * @param align the row's new vertical alignment as specified in
     *          {@link HasVerticalAlignment}
     * @throws IndexOutOfBoundsException
     */
    public void setVerticalAlign(int row, VerticalAlignmentConstant align) {
      ensureElement(row).getStyle().setProperty("verticalAlign", align.getVerticalAlignString());
    }

    /**
     * Sets whether this row is visible.
     * 
     * @param row the row whose visibility is to be set
     * @param visible <code>true</code> to show the row, <code>false</code> to
     *          hide it
     */
    public void setVisible(int row, boolean visible) {
      Element e = ensureElement(row);
      UIObject.setVisible(e, visible);
    }

    /**
     * Ensure the TR element representing the specified row exists for
     * subclasses that allow dynamic addition of elements.
     * 
     * @param row the row whose TR element is to be retrieved
     * @return the row's TR element
     * @throws IndexOutOfBoundsException
     */
    protected com.google.gwt.user.client.Element ensureElement(int row) {
      prepareRow(row);
      return DOM.asOld(getRow(bodyElem, row));
    }

    @SuppressWarnings("deprecation")
    protected com.google.gwt.user.client.Element getRow(Element tbody, int row) {
      return getRow(DOM.asOld(tbody), row);
    }

    /**
     * @deprecated Call and override {@link #getRow(Element, int)} instead.
     */
    @Deprecated
    protected com.google.gwt.user.client.Element getRow(
        com.google.gwt.user.client.Element tbody, int row) {
      return DOM.asOld(impl.getRows(tbody).get(row));
    }

    /**
     * Convenience methods to set an attribute on a row.
     * 
     * @param row cell's row
     * @param attrName attribute to set
     * @param value value to set
     * @throws IndexOutOfBoundsException
     */
    protected void setAttr(int row, String attrName, String value) {
      Element elem = ensureElement(row);
      elem.setAttribute(attrName, value);
    }
  }

  private static final HTMLTableImpl impl = GWT.create(HTMLTableImpl.class);

  /**
   * Table's body.
   */
  private final Element bodyElem;

  /**
   * Current cell formatter.
   */
  private CellFormatter cellFormatter;

  /**
   * Column Formatter.
   */
  private ColumnFormatter columnFormatter;

  /**
   * Current row formatter.
   */
  private RowFormatter rowFormatter;

  /**
   * Table element.
   */
  private final Element tableElem;

  private ElementMapperImpl<Widget> widgetMap = new ElementMapperImpl<Widget>();

  /**
   * Create a new empty HTML Table.
   */
  public HTMLTable() {
    tableElem = DOM.createTable();
    bodyElem = DOM.createTBody();
    DOM.appendChild(tableElem, bodyElem);
    setElement(tableElem);
  }

  public HandlerRegistration addClickHandler(ClickHandler handler) {
    return addDomHandler(handler, ClickEvent.getType());
  }

  public HandlerRegistration addDoubleClickHandler(DoubleClickHandler handler) {
    return addDomHandler(handler, DoubleClickEvent.getType());
  }

  public HandlerRegistration addDragEndHandler(DragEndHandler handler) {
    return addBitlessDomHandler(handler, DragEndEvent.getType());
  }

  public HandlerRegistration addDragEnterHandler(DragEnterHandler handler) {
    return addBitlessDomHandler(handler, DragEnterEvent.getType());
  }

  public HandlerRegistration addDragHandler(DragHandler handler) {
    return addBitlessDomHandler(handler, DragEvent.getType());
  }

  public HandlerRegistration addDragLeaveHandler(DragLeaveHandler handler) {
    return addBitlessDomHandler(handler, DragLeaveEvent.getType());
  }

  public HandlerRegistration addDragOverHandler(DragOverHandler handler) {
    return addBitlessDomHandler(handler, DragOverEvent.getType());
  }

  public HandlerRegistration addDragStartHandler(DragStartHandler handler) {
    return addBitlessDomHandler(handler, DragStartEvent.getType());
  }

  public HandlerRegistration addDropHandler(DropHandler handler) {
    return addBitlessDomHandler(handler, DropEvent.getType());
  }

  /**
   * Adds a listener to the current table.
   * 
   * @param listener listener to add
   * @deprecated add a click handler instead and use
   *             {@link HTMLTable#getCellForEvent(ClickEvent)} to get the cell
   *             information (remember to check for a null return value)
   */
  @Deprecated
  public void addTableListener(TableListener listener) {
    ListenerWrapper.WrappedTableListener.add(this, listener);
  }

  /**
   * Removes all widgets from this table, but does not remove other HTML or text
   * contents of cells.
   */
  @Override
  public void clear() {
    clear(false);
  }

  /**
   * Removes all widgets from this table, optionally clearing the inner HTML of
   * each cell.  Note that this method does not remove any cells or rows.
   * 
   * @param clearInnerHTML should the cell's inner html be cleared?
   */
  public void clear(boolean clearInnerHTML) {
    for (int row = 0; row < getRowCount(); ++row) {
      for (int col = 0; col < getCellCount(row); ++col) {
        cleanCell(row, col, clearInnerHTML);
      }
    }
  }

  /**
   * Clears the cell at the given row and column. If it contains a Widget, it
   * will be removed from the table. If not, its contents will simply be
   * cleared.
   * 
   * @param row the widget's row
   * @param column the widget's column
   * @return true if a widget was removed
   * @throws IndexOutOfBoundsException
   */
  public boolean clearCell(int row, int column) {
    Element td = getCellFormatter().getElement(row, column);
    return internalClearCell(td, true);
  }

  /**
   * Gets the number of cells in a given row.
   * 
   * @param row the row whose cells are to be counted
   * @return the number of cells present in the row
   */
  public abstract int getCellCount(int row);

  /**
   * Given a click event, return the Cell that was clicked, or null if the event
   * did not hit this table.  The cell can also be null if the click event does
   * not occur on a specific cell.
   * 
   * @param event A click event of indeterminate origin
   * @return The appropriate cell, or null
   */
  public Cell getCellForEvent(ClickEvent event) {
    Element td = getEventTargetCell(Event.as(event.getNativeEvent()));
    if (td == null) {
      return null;
    }

    int row = TableRowElement.as(td.getParentElement()).getSectionRowIndex();
    int column = TableCellElement.as(td).getCellIndex();
    return new Cell(row, column);
  }

  /**
   * Gets the {@link CellFormatter} associated with this table. Use casting to
   * get subclass-specific functionality
   * 
   * @return this table's cell formatter
   */
  public CellFormatter getCellFormatter() {
    return cellFormatter;
  }

  /**
   * Gets the amount of padding that is added around all cells.
   * 
   * @return the cell padding, in pixels
   */
  public int getCellPadding() {
    return tableElem.getPropertyInt("cellPadding");
  }

  /**
   * Gets the amount of spacing that is added around all cells.
   * 
   * @return the cell spacing, in pixels
   */
  public int getCellSpacing() {
    return tableElem.getPropertyInt("cellSpacing");
  }

  /**
   * Gets the column formatter.
   * 
   * @return the column formatter
   */
  public ColumnFormatter getColumnFormatter() {
    return columnFormatter;
  }

  /**
   * Gets the HTML contents of the specified cell.
   * 
   * @param row the cell's row
   * @param column the cell's column
   * @return the cell's HTML contents
   * @throws IndexOutOfBoundsException
   */
  public String getHTML(int row, int column) {
    return cellFormatter.getElement(row, column).getInnerHTML();
  }

  /**
   * Gets the number of rows present in this table.
   * 
   * @return the table's row count
   */
  public abstract int getRowCount();

  /**
   * Gets the RowFormatter associated with this table.
   * 
   * @return the table's row formatter
   */
  public RowFormatter getRowFormatter() {
    return rowFormatter;
  }

  /**
   * Gets the text within the specified cell.
   * 
   * @param row the cell's row
   * @param column the cell's column
   * @return the cell's text contents
   * @throws IndexOutOfBoundsException
   */
  public String getText(int row, int column) {
    checkCellBounds(row, column);
    Element e = cellFormatter.getElement(row, column);
    return e.getInnerText();
  }

  /**
   * Gets the widget in the specified cell.
   * 
   * @param row the cell's row
   * @param column the cell's column
   * @return the widget in the specified cell, or <code>null</code> if none is
   *         present
   * @throws IndexOutOfBoundsException
   */
  public Widget getWidget(int row, int column) {
    checkCellBounds(row, column);
    return getWidgetImpl(row, column);
  }

  /**
   * Determines whether the specified cell exists.
   * 
   * @param row the cell's row
   * @param column the cell's column
   * @return <code>true</code> if the specified cell exists
   */
  public boolean isCellPresent(int row, int column) {
    if ((row >= getRowCount()) || (row < 0)) {
      return false;
    }
    if ((column < 0) || (column >= getCellCount(row))) {
      return false;
    } else {
      return true;
    }
  }

  /**
   * Returns an iterator containing all the widgets in this table.
   * 
   * @return the iterator
   */
  public Iterator<Widget> iterator() {
    return new Iterator<Widget>() {
      final ArrayList<Widget> widgetList = widgetMap.getObjectList();
      int lastIndex = -1;
      int nextIndex = -1;
      {
        findNext();
      }

      public boolean hasNext() {
        return nextIndex < widgetList.size();
      }

      public Widget next() {
        if (!hasNext()) {
          throw new NoSuchElementException();
        }
        Widget result = widgetList.get(nextIndex);
        lastIndex = nextIndex;
        findNext();
        return result;
      }

      public void remove() {
        if (lastIndex < 0) {
          throw new IllegalStateException();
        }
        Widget w = widgetList.get(lastIndex);
        assert (w.getParent() instanceof HTMLTable);
        w.removeFromParent();
        lastIndex = -1;
      }

      private void findNext() {
        while (++nextIndex < widgetList.size()) {
          if (widgetList.get(nextIndex) != null) {
            return;
          }
        }
      }
    };
  }

  /**
   * Remove the specified widget from the table.
   * 
   * @param widget widget to remove
   * @return was the widget removed from the table.
   */
  @Override
  public boolean remove(Widget widget) {
    // Validate.
    if (widget.getParent() != this) {
      return false;
    }

    // Orphan.
    try {
      orphan(widget);
    } finally {
      // Physical detach.
      Element elem = widget.getElement();
      DOM.getParent(elem).removeChild(elem);
  
      // Logical detach.
      widgetMap.removeByElement(elem);
    }
    return true;
  }

  /**
   * Removes the specified table listener.
   * 
   * @param listener listener to remove
   *
   * @deprecated Use the {@link HandlerRegistration#removeHandler}
   * method on the object returned by an add*Handler method instead
   */
  @Deprecated
  public void removeTableListener(TableListener listener) {
    ListenerWrapper.WrappedTableListener.remove(this, listener);
  }

  /**
   * Sets the width of the table's border. This border is displayed around all
   * cells in the table.
   * 
   * @param width the width of the border, in pixels
   */
  public void setBorderWidth(int width) {
    tableElem.setPropertyString("border", "" + width);
  }

  /**
   * Sets the amount of padding to be added around all cells.
   * 
   * @param padding the cell padding, in pixels
   */
  public void setCellPadding(int padding) {
    tableElem.setPropertyInt("cellPadding", padding);
  }

  /**
   * Sets the amount of spacing to be added around all cells.
   * 
   * @param spacing the cell spacing, in pixels
   */
  public void setCellSpacing(int spacing) {
    tableElem.setPropertyInt("cellSpacing", spacing);
  }

  /**
   * Sets the HTML contents of the specified cell.
   *
   * @param row the cell's row
   * @param column the cell's column
   * @param html the cell's HTML contents
   * @throws IndexOutOfBoundsException
   */
  public void setHTML(int row, int column, @IsSafeHtml String html) {
    prepareCell(row, column);
    Element td = cleanCell(row, column, html == null);
    if (html != null) {
      td.setInnerHTML(html);
    }
  }

  /**
   * Sets the HTML contents of the specified cell.
   *
   * @param row the cell's row
   * @param column the cell's column
   * @param html the cell's safe html contents
   * @throws IndexOutOfBoundsException
   */
  public void setHTML(int row, int column, SafeHtml html) {
    setHTML(row, column, html.asString());
  }

  /**
   * Sets the text within the specified cell.
   *
   * @param row the cell's row
   * @param column cell's column
   * @param text the cell's text contents
   * @throws IndexOutOfBoundsException
   */
  public void setText(int row, int column, String text) {
    prepareCell(row, column);
    Element td;
    td = cleanCell(row, column, text == null);
    if (text != null) {
      td.setInnerText(text);
    }
  }

  /**
   * Sets the widget within the specified cell.
   * <p>
   * Inherited implementations may either throw IndexOutOfBounds exception if
   * the cell does not exist, or allocate a new cell to store the content.
   * </p>
   * <p>
   * FlexTable will automatically allocate the cell at the correct location and
   * then set the widget. Grid will set the widget if and only if the cell is
   * within the Grid's bounding box.
   * </p>
   * 
   * @param widget The widget to be added, or null to clear the cell
   * @param row the cell's row
   * @param column the cell's column
   * @throws IndexOutOfBoundsException
   */
  public void setWidget(int row, int column, Widget widget) {
    prepareCell(row, column);

    // Removes any existing widget.
    Element td = cleanCell(row, column, true);

    if (widget != null) {
      widget.removeFromParent();

      // Logical attach.
      widgetMap.put(widget);

      // Physical attach.
      DOM.appendChild(td, widget.getElement());

      adopt(widget);
    }
  }
  
  /**
   * Overloaded version for IsWidget.
   * 
   * @see #setWidget(int,int,Widget)
   */
  public void setWidget(int row, int column, IsWidget widget) {
    this.setWidget(row, column, asWidgetOrNull(widget));
  }

  /**
   * Bounds checks that the cell exists at the specified location.
   * 
   * @param row cell's row
   * @param column cell's column
   * @throws IndexOutOfBoundsException
   */
  protected void checkCellBounds(int row, int column) {
    checkRowBounds(row);
    if (column < 0) {
      throw new IndexOutOfBoundsException("Column " + column
          + " must be non-negative: " + column);
    }
    int cellSize = getCellCount(row);
    if (cellSize <= column) {
      throw new IndexOutOfBoundsException("Column index: " + column
          + ", Column size: " + getCellCount(row));
    }
  }

  /**
   * Checks that the row is within the correct bounds.
   * 
   * @param row row index to check
   * @throws IndexOutOfBoundsException
   */
  protected void checkRowBounds(int row) {
    int rowSize = getRowCount();
    if ((row >= rowSize) || (row < 0)) {
      throw new IndexOutOfBoundsException("Row index: " + row + ", Row size: "
          + rowSize);
    }
  }

  /**
   * Creates a new cell. Override this method if the cell should have initial
   * contents.
   * 
   * @return the newly created TD
   */
  protected com.google.gwt.user.client.Element createCell() {
    return DOM.createTD();
  }

  /**
   * Gets the table's TBODY element.
   * 
   * @return the TBODY element
   */
  protected com.google.gwt.user.client.Element getBodyElement() {
    return DOM.asOld(bodyElem);
  }

  /**
   * Directly ask the underlying DOM what the cell count on the given row is.
   * 
   * @param tableBody the element
   * @param row the row
   * @return number of columns in the row
   */
  @SuppressWarnings("deprecation")
  protected int getDOMCellCount(Element tableBody, int row) {
    return getDOMCellCount(DOM.asOld(tableBody), row);
  }

  /**
   * @deprecated Call and override {@link #getDOMCellCount(Element, int)} instead.
   */
  @Deprecated
  protected int getDOMCellCount(com.google.gwt.user.client.Element tableBody, int row) {
    Element rowElement = impl.getRows(tableBody).get(row);
    return impl.getCells(rowElement).length();
  }

  /**
   * Directly ask the underlying DOM what the cell count on the given row is.
   * 
   * @param row the row
   * @return number of columns in the row
   */
  protected int getDOMCellCount(int row) {
    return getDOMCellCount(bodyElem, row);
  }

  /**
   * Directly ask the underlying DOM what the row count is.
   * 
   * @return Returns the number of rows in the table
   */
  protected int getDOMRowCount() {
    return getDOMRowCount(bodyElem);
  }

  @SuppressWarnings("deprecation")
  protected int getDOMRowCount(Element tbody) {
    return getDOMRowCount(DOM.asOld(tbody));
  }

  /**
   * @deprecated Call and override {@link #getDOMRowCount(Element)} instead.
   */
  @Deprecated
  protected int getDOMRowCount(com.google.gwt.user.client.Element tbody) {
    return impl.getRows(tbody).length();
  }

  /**
   * Determines the TD associated with the specified event.
   * 
   * @param event the event to be queried
   * @return the TD associated with the event, or <code>null</code> if none is
   *         found.
   */
  protected com.google.gwt.user.client.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 (td.getPropertyString("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);
        if (body == bodyElem) {
          return DOM.asOld(td);
        }
      }
      // If we run into this table's body, we're out of options.
      if (td == bodyElem) {
        return null;
      }
    }
    return null;
  }

  /**
   * Inserts a new cell into the specified row.
   * 
   * @param row the row into which the new cell will be inserted
   * @param column the column before which the cell will be inserted
   * @throws IndexOutOfBoundsException
   */
  protected void insertCell(int row, int column) {
    Element tr = rowFormatter.getRow(bodyElem, row);
    Element td = createCell();
    DOM.insertChild(tr, td, column);
  }

  /**
   * Inserts a number of cells before the specified cell.
   * 
   * @param row the row into which the new cells will be inserted
   * @param column the column before which the new cells will be inserted
   * @param count number of cells to be inserted
   * @throws IndexOutOfBoundsException
   */
  protected void insertCells(int row, int column, int count) {
    Element tr = rowFormatter.getRow(bodyElem, row);
    for (int i = column; i < column + count; i++) {
      Element td = createCell();
      DOM.insertChild(tr, td, i);
    }
  }

  /**
   * Inserts a new row into the table.
   * 
   * @param beforeRow the index before which the new row will be inserted
   * @return the index of the newly-created row
   * @throws IndexOutOfBoundsException
   */
  protected int insertRow(int beforeRow) {
    // Specifically allow the row count as an insert position.
    if (beforeRow != getRowCount()) {
      checkRowBounds(beforeRow);
    }
    Element tr = DOM.createTR();
    DOM.insertChild(bodyElem, tr, beforeRow);
    return beforeRow;
  }

  /**
   * Does actual clearing, used by clearCell and cleanCell. All HTMLTable
   * methods should use internalClearCell rather than clearCell, as clearCell
   * may be overridden in subclasses to format an empty cell.
   * 
   * @param td element to clear
   * @param clearInnerHTML should the cell's inner html be cleared?
   * @return returns whether a widget was cleared
   */
  @SuppressWarnings("deprecation")
  protected boolean internalClearCell(Element td, boolean clearInnerHTML) {
    return internalClearCell(DOM.asOld(td), clearInnerHTML);
  }

  /**
   * @deprecated Call and override {@link internalClearCell(Element, boolean)} instead.
   */
  @Deprecated
  protected boolean internalClearCell(com.google.gwt.user.client.Element td,
      boolean clearInnerHTML) {
    Element maybeChild = DOM.getFirstChild(td);
    Widget widget = null;
    if (maybeChild != null) {
      widget = widgetMap.get(maybeChild);
    }
    if (widget != null) {
      // If there is a widget, remove it.
      remove(widget);
      return true;
    } else {
      // Otherwise, simply clear whatever text and/or HTML may be there.
      if (clearInnerHTML) {
        td.setInnerHTML("");
      }
      return false;
    }
  }

  /**
   * <b>Affected Elements:</b>
   * <ul>
   * <li>-(row)#-(cell)# = the cell at the given row and cell index.</li>
   * </ul>
   * 
   * @see UIObject#onEnsureDebugId(String)
   */
  @Override
  protected void onEnsureDebugId(String baseID) {
    super.onEnsureDebugId(baseID);

    int rowCount = getRowCount();
    for (int row = 0; row < rowCount; row++) {
      int cellCount = getCellCount(row);
      for (int cell = 0; cell < cellCount; cell++) {
        Element cellElem = cellFormatter.getRawElement(row, cell);
        ensureDebugId(cellElem, baseID, row + "-" + cell);
      }
    }
  }

  /**
   * Subclasses must implement this method. It allows them to decide what to do
   * just before a cell is accessed. If the cell already exists, this method
   * must do nothing. Otherwise, a subclass must either ensure that the cell
   * exists or throw an {@link IndexOutOfBoundsException}.
   * 
   * @param row the cell's row
   * @param column the cell's column
   */
  protected abstract void prepareCell(int row, int column);

  /**
   * Subclasses can implement this method. It allows them to decide what to do
   * just before a column is accessed. For classes, such as
   * <code>FlexTable</code>, that do not have a concept of a global column
   * length can ignore this method.
   * 
   * @param column the cell's column
   * @throws IndexOutOfBoundsException
   */
  protected void prepareColumn(int column) {
    // Ensure that the indices are not negative.
    if (column < 0) {
      throw new IndexOutOfBoundsException(
          "Cannot access a column with a negative index: " + column);
    }
  }

  /**
   * Subclasses must implement this method. If the row already exists, this
   * method must do nothing. Otherwise, a subclass must either ensure that the
   * row exists or throw an {@link IndexOutOfBoundsException}.
   * 
   * @param row the cell's row
   */
  protected abstract void prepareRow(int row);

  /**
   * Removes the specified cell from the table.
   * 
   * @param row the row of the cell to remove
   * @param column the column of cell to remove
   * @throws IndexOutOfBoundsException
   */
  protected void removeCell(int row, int column) {
    checkCellBounds(row, column);
    Element td = cleanCell(row, column, false);
    Element tr = rowFormatter.getRow(bodyElem, row);
    tr.removeChild(td);
  }

  /**
   * Removes the specified row from the table.
   * 
   * @param row the index of the row to be removed
   * @throws IndexOutOfBoundsException
   */
  protected void removeRow(int row) {
    int columnCount = getCellCount(row);
    for (int column = 0; column < columnCount; ++column) {
      cleanCell(row, column, false);
    }
    bodyElem.removeChild(rowFormatter.getRow(bodyElem, row));
  }

  /**
   * Sets the table's CellFormatter.
   * 
   * @param cellFormatter the table's cell formatter
   */
  protected void setCellFormatter(CellFormatter cellFormatter) {
    this.cellFormatter = cellFormatter;
  }

  protected void setColumnFormatter(ColumnFormatter formatter) {
    // Copy the columnGroup element to the new formatter so we don't create a
    // second colgroup element.
    if (columnFormatter != null) {
      formatter.columnGroup = columnFormatter.columnGroup;
    }
    columnFormatter = formatter;
    columnFormatter.prepareColumnGroup();
  }

  /**
   * Sets the table's RowFormatter.
   * 
   * @param rowFormatter the table's row formatter
   */
  protected void setRowFormatter(RowFormatter rowFormatter) {
    this.rowFormatter = rowFormatter;
  }

  void addCells(Element tbody, int row, int num) {
    com.google.gwt.dom.client.Element rowElem = impl.getRows(tbody).get(row);
    for (int i = 0; i < num; i++) {
      TableCellElement tdElement = Document.get().createTDElement();
      rowElem.appendChild(tdElement);
    }
  }

  /**
   * Removes any widgets, text, and HTML within the cell. This method assumes
   * that the requested cell already exists.
   * 
   * @param row the cell's row
   * @param column the cell's column
   * @param clearInnerHTML should the cell's inner html be cleared?
   * @return element that has been cleaned
   */
  private Element cleanCell(int row, int column, boolean clearInnerHTML) {
    // Clear whatever is in the cell.
    Element td = getCellFormatter().getRawElement(row, column);
    internalClearCell(td, clearInnerHTML);
    return td;
  }

  /**
   * Gets the Widget associated with the given cell.
   * 
   * @param row the cell's row
   * @param column the cell's column
   * @return the widget
   */
  private Widget getWidgetImpl(int row, int column) {
    Element e = cellFormatter.getRawElement(row, column);
    Element child = DOM.getFirstChild(e);
    if (child == null) {
      return null;
    } else {
      return widgetMap.get(child);
    }
  }
}
