/*
 * Copyright 2010 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.cellview.client;

import com.google.gwt.cell.client.Cell;
import com.google.gwt.cell.client.Cell.Context;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.cell.client.HasCell;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.builder.shared.HtmlTableSectionBuilder;
import com.google.gwt.dom.builder.shared.TableSectionBuilder;
import com.google.gwt.dom.client.BrowserEvents;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.TableCellElement;
import com.google.gwt.dom.client.TableElement;
import com.google.gwt.dom.client.TableRowElement;
import com.google.gwt.dom.client.TableSectionElement;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasHorizontalAlignment.HorizontalAlignmentConstant;
import com.google.gwt.user.client.ui.HasVerticalAlignment.VerticalAlignmentConstant;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.CellPreviewEvent;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.SelectionModel;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Abstract base class for tabular views that supports paging and columns.
 * 
 * <p>
 * <h3>Columns</h3> The {@link Column} class defines the {@link Cell} used to
 * render a column. Implement {@link Column#getValue(Object)} to retrieve the
 * field value from the row object that will be rendered in the {@link Cell}.
 * </p>
 * 
 * <p>
 * <h3>Headers and Footers</h3> A {@link Header} can be placed at the top
 * (header) or bottom (footer) of the {@link AbstractCellTable}. You can specify
 * a header as text using {@link #addColumn(Column, String)}, or you can create
 * a custom {@link Header} that can change with the value of the cells, such as
 * a column total. The {@link Header} will be rendered every time the row data
 * changes or the table is redrawn. If you pass the same header instance (==)
 * into adjacent columns, the header will span the columns.
 * </p>
 * 
 * @param <T> the data type of each row
 */
public abstract class AbstractCellTable<T> extends AbstractHasData<T> {

  /**
   * Default implementation of a keyboard navigation handler for tables that
   * supports navigation between cells.
   * 
   * @param <T> the data type of each row
   */
  public static class CellTableKeyboardSelectionHandler<T> extends
      DefaultKeyboardSelectionHandler<T> {

    private final AbstractCellTable<T> table;

    /**
     * Construct a new keyboard selection handler for the specified table.
     * 
     * @param table the display being handled
     */
    public CellTableKeyboardSelectionHandler(AbstractCellTable<T> table) {
      super(table);
      this.table = table;
    }

    @Override
    public AbstractCellTable<T> getDisplay() {
      return table;
    }

    @Override
    public void onCellPreview(CellPreviewEvent<T> event) {
      NativeEvent nativeEvent = event.getNativeEvent();
      String eventType = event.getNativeEvent().getType();
      if (BrowserEvents.KEYDOWN.equals(eventType) && !event.isCellEditing()) {
        /*
         * Handle keyboard navigation, unless the cell is being edited. If the
         * cell is being edited, we do not want to change rows.
         * 
         * Prevent default on navigation events to prevent default scrollbar
         * behavior.
         */
        int oldRow = table.getKeyboardSelectedRow();
        int oldColumn = table.getKeyboardSelectedColumn();
        boolean isRtl = LocaleInfo.getCurrentLocale().isRTL();
        int keyCodeLineEnd = isRtl ? KeyCodes.KEY_LEFT : KeyCodes.KEY_RIGHT;
        int keyCodeLineStart = isRtl ? KeyCodes.KEY_RIGHT : KeyCodes.KEY_LEFT;
        int keyCode = nativeEvent.getKeyCode();
        if (keyCode == keyCodeLineEnd) {
          int nextColumn = findInteractiveColumn(oldColumn, false);
          if (nextColumn <= oldColumn) {
            // Wrap to the next row.
            table.setKeyboardSelectedRow(oldRow + 1);
            if (table.getKeyboardSelectedRow() != oldRow) {
              // If the row didn't change, we are at the end of the table.
              table.setKeyboardSelectedColumn(nextColumn);
              handledEvent(event);
              return;
            }
          } else {
            table.setKeyboardSelectedColumn(nextColumn);
            handledEvent(event);
            return;
          }
        } else if (keyCode == keyCodeLineStart) {
          int prevColumn = findInteractiveColumn(oldColumn, true);
          if (prevColumn >= oldColumn) {
            // Wrap to the previous row.
            table.setKeyboardSelectedRow(oldRow - 1);
            if (table.getKeyboardSelectedRow() != oldRow) {
              // If the row didn't change, we are at the start of the table.
              table.setKeyboardSelectedColumn(prevColumn);
              handledEvent(event);
              return;
            }
          } else {
            table.setKeyboardSelectedColumn(prevColumn);
            handledEvent(event);
            return;
          }
        }
      } else if (BrowserEvents.CLICK.equals(eventType) || BrowserEvents.FOCUS.equals(eventType)) {
        /*
         * Move keyboard focus to the clicked column, even if the cell is being
         * edited. Unlike key events, we aren't moving the currently selected
         * row, just updating it based on where the user clicked.
         * 
         * Since the user clicked, allow focus to go to a non-interactive
         * column.
         */
        int col = event.getColumn();
        int relRow = event.getIndex() - table.getPageStart();
        int subrow = event.getContext().getSubIndex();
        if ((table.getKeyboardSelectedColumn() != col)
            || (table.getKeyboardSelectedRow() != relRow)
            || (table.getKeyboardSelectedSubRow() != subrow)) {
          boolean stealFocus = false;
          if (BrowserEvents.CLICK.equals(eventType)) {
            // If a natively focusable element was just clicked, then do not
            // steal focus.
            Element target = Element.as(event.getNativeEvent().getEventTarget());
            stealFocus = !CellBasedWidgetImpl.get().isFocusable(target);
          }

          // Update the row and subrow.
          table.setKeyboardSelectedRow(relRow, subrow, stealFocus);

          // Update the column index.
          table.setKeyboardSelectedColumn(col, stealFocus);
        }

        // Do not cancel the event as the click may have occurred on a Cell.
        return;
      }

      // Let the parent class handle the event.
      super.onCellPreview(event);
    }

    /**
     * Find and return the index of the next interactive column. If no column is
     * interactive, 0 is returned. If the start index is the only interactive
     * column, it is returned.
     * 
     * @param start the start index, exclusive unless it is the only option
     * @param reverse true to do a reverse search
     * @return the interactive column index, or 0 if not interactive
     */
    private int findInteractiveColumn(int start, boolean reverse) {
      if (!table.isInteractive) {
        return 0;
      } else if (reverse) {
        for (int i = start - 1; i >= 0; i--) {
          if (isColumnInteractive(table.getColumn(i))) {
            return i;
          }
        }
        // Wrap to the end.
        for (int i = table.getColumnCount() - 1; i >= start; i--) {
          if (isColumnInteractive(table.getColumn(i))) {
            return i;
          }
        }
      } else {
        for (int i = start + 1; i < table.getColumnCount(); i++) {
          if (isColumnInteractive(table.getColumn(i))) {
            return i;
          }
        }
        // Wrap to the start.
        for (int i = 0; i <= start; i++) {
          if (isColumnInteractive(table.getColumn(i))) {
            return i;
          }
        }
      }
      return 0;
    }
  }

  /**
   * A ClientBundle that provides images for this widget.
   */
  public interface Resources {
    /**
     * Icon used when a column is sorted in ascending order.
     */
    ImageResource sortAscending();

    /**
     * Icon used when a column is sorted in descending order.
     */
    ImageResource sortDescending();

    /**
     * The styles used in this widget.
     */
    Style style();
  }

  /**
   * Styles used by this widget.
   */
  public interface Style {
    /**
     * Applied to every cell.
     */
    String cell();

    /**
     * Applied to even rows.
     */
    String evenRow();

    /**
     * Applied to cells in even rows.
     */
    String evenRowCell();

    /**
     * Applied to the first column.
     */
    String firstColumn();

    /**
     * Applied to the first column footers.
     */
    String firstColumnFooter();

    /**
     * Applied to the first column headers.
     */
    String firstColumnHeader();

    /**
     * Applied to footers cells.
     */
    String footer();

    /**
     * Applied to headers cells.
     */
    String header();

    /**
     * Applied to the hovered row.
     */
    String hoveredRow();

    /**
     * Applied to the cells in the hovered row.
     */
    String hoveredRowCell();

    /**
     * Applied to the keyboard selected cell.
     */
    String keyboardSelectedCell();

    /**
     * Applied to the keyboard selected row.
     */
    String keyboardSelectedRow();

    /**
     * Applied to the cells in the keyboard selected row.
     */
    String keyboardSelectedRowCell();

    /**
     * Applied to the last column.
     */
    String lastColumn();

    /**
     * Applied to the last column footers.
     */
    String lastColumnFooter();

    /**
     * Applied to the last column headers.
     */
    String lastColumnHeader();

    /**
     * Applied to odd rows.
     */
    String oddRow();

    /**
     * Applied to cells in odd rows.
     */
    String oddRowCell();

    /**
     * Applied to selected rows.
     */
    String selectedRow();

    /**
     * Applied to cells in selected rows.
     */
    String selectedRowCell();

    /**
     * Applied to header cells that are sortable.
     */
    String sortableHeader();

    /**
     * Applied to header cells that are sorted in ascending order.
     */
    String sortedHeaderAscending();

    /**
     * Applied to header cells that are sorted in descending order.
     */
    String sortedHeaderDescending();

    /**
     * Applied to the table.
     */
    String widget();
  }

  /**
   * Interface that this class's subclass may implement to get notified with table section change
   * event. During rendering, a faster method based on swaping the entire section will be used iff
   * <li> it's in IE - since all other optimizations have been turned off
   * <li> the table implements TableSectionChangeHandler interface
   * When a section is being replaced by another table with the new table html, the methods in this
   * interface will be invoked with the changed section. The table should update its internal
   * references to the sections properly so that when {@link #getTableBodyElement},
   * {@link #getTableHeadElement}, or {@link #getTableFootElement} are called, the correct section
   * will be returned.
   */
  protected interface TableSectionChangeHandler {
    /**
     * Notify that a table body section has been changed.
     * @param newTBody the new body section
     */
    void onTableBodyChange(TableSectionElement newTBody);

    /**
     * Notify that a table body section has been changed.
     * @param newTFoot the new foot section
     */
    void onTableFootChange(TableSectionElement newTFoot);
    
    /**
     * Notify that a table head section has been changed.
     * @param newTHead the new head section
     */
    void onTableHeadChange(TableSectionElement newTHead);
  }
  
  interface Template extends SafeHtmlTemplates {
    @SafeHtmlTemplates.Template("<div style=\"outline:none;\">{0}</div>")
    SafeHtml div(SafeHtml contents);

    @SafeHtmlTemplates.Template("<table><tbody>{0}</tbody></table>")
    SafeHtml tbody(SafeHtml rowHtml);

    @SafeHtmlTemplates.Template("<td class=\"{0}\">{1}</td>")
    SafeHtml td(String classes, SafeHtml contents);

    @SafeHtmlTemplates.Template("<td class=\"{0}\" align=\"{1}\" valign=\"{2}\">{3}</td>")
    SafeHtml tdBothAlign(String classes, String hAlign, String vAlign, SafeHtml contents);

    @SafeHtmlTemplates.Template("<td class=\"{0}\" align=\"{1}\">{2}</td>")
    SafeHtml tdHorizontalAlign(String classes, String hAlign, SafeHtml contents);

    @SafeHtmlTemplates.Template("<td class=\"{0}\" valign=\"{1}\">{2}</td>")
    SafeHtml tdVerticalAlign(String classes, String vAlign, SafeHtml contents);

    @SafeHtmlTemplates.Template("<table><tfoot>{0}</tfoot></table>")
    SafeHtml tfoot(SafeHtml rowHtml);

    @SafeHtmlTemplates.Template("<table><thead>{0}</thead></table>")
    SafeHtml thead(SafeHtml rowHtml);

    @SafeHtmlTemplates.Template("<tr onclick=\"\" class=\"{0}\">{1}</tr>")
    SafeHtml tr(String classes, SafeHtml contents);
  }

  /**
   * Implementation of {@link AbstractCellTable}.
   */
  private static class Impl {

    private final com.google.gwt.user.client.Element tmpElem = Document.get().createDivElement()
        .cast();

    /**
     * Convert the rowHtml into Elements wrapped by the specified table section.
     * 
     * @param table the {@link AbstractCellTable}
     * @param sectionTag the table section tag
     * @param rowHtml the Html for the rows
     * @return the section element
     */
    public TableSectionElement convertToSectionElement(AbstractCellTable<?> table,
        String sectionTag, SafeHtml rowHtml) {
      // Attach an event listener so we can catch synchronous load events from
      // cached images.
      DOM.setEventListener(tmpElem, table);

      /*
       * Render the rows into a table.
       * 
       * IE doesn't support innerHtml on a TableSection or Table element, so we
       * generate the entire table. We do the same for all browsers to avoid any
       * future bugs, since setting innerHTML on a table section seems brittle.
       */
      sectionTag = sectionTag.toLowerCase();
      if ("tbody".equals(sectionTag)) {
        tmpElem.setInnerSafeHtml(template.tbody(rowHtml));
      } else if ("thead".equals(sectionTag)) {
        tmpElem.setInnerSafeHtml(template.thead(rowHtml));
      } else if ("tfoot".equals(sectionTag)) {
        tmpElem.setInnerSafeHtml(template.tfoot(rowHtml));
      } else {
        throw new IllegalArgumentException("Invalid table section tag: " + sectionTag);
      }
      TableElement tableElem = tmpElem.getFirstChildElement().cast();

      // Detach the event listener.
      DOM.setEventListener(tmpElem, null);

      // Get the section out of the table.
      if ("tbody".equals(sectionTag)) {
        return tableElem.getTBodies().getItem(0);
      } else if ("thead".equals(sectionTag)) {
        return tableElem.getTHead();
      } else if ("tfoot".equals(sectionTag)) {
        return tableElem.getTFoot();
      } else {
        throw new IllegalArgumentException("Invalid table section tag: " + sectionTag);
      }
    }

    /**
     * Render a table section in the table.
     * 
     * @param table the {@link AbstractCellTable}
     * @param section the {@link TableSectionElement} to replace
     * @param html the html of a table section element containing the rows
     */
    public final void replaceAllRows(AbstractCellTable<?> table, TableSectionElement section,
        SafeHtml html) {
      // If the widget is not attached, attach an event listener so we can catch
      // synchronous load events from cached images.
      if (!table.isAttached()) {
        DOM.setEventListener(table.getElement(), table);
      }

      // Remove the section from the tbody.
      Element parent = section.getParentElement();
      Element nextSection = section.getNextSiblingElement();
      detachSectionElement(section);

      // Render the html.
      replaceAllRowsImpl(table, section, html);

      /*
       * Reattach the section. If next section is null, the section will be
       * appended instead.
       */
      reattachSectionElement(parent, section, nextSection);

      // Detach the event listener.
      if (!table.isAttached()) {
        DOM.setEventListener(table.getElement(), null);
      }
    }

    /**
     * Replace a set of row values with newly rendered values.
     * 
     * This method does not necessarily perform a one to one replacement. Some
     * row values may be rendered as multiple row elements, while others are
     * rendered as only one row element.
     * 
     * @param table the {@link AbstractCellTable}
     * @param section the {@link TableSectionElement} to replace
     * @param html the html of a table section element containing the rows
     * @param startIndex the start index to replace
     * @param childCount the number of row values to replace
     */
    public final void replaceChildren(AbstractCellTable<?> table, TableSectionElement section,
        SafeHtml html, int startIndex, int childCount) {
      // If the widget is not attached, attach an event listener so we can catch
      // synchronous load events from cached images.
      if (!table.isAttached()) {
        DOM.setEventListener(table.getElement(), table);
      }

      // Remove the section from the tbody.
      Element parent = section.getParentElement();
      Element nextSection = section.getNextSiblingElement();
      detachSectionElement(section);

      // Remove all children in the range.
      final int absEndIndex = table.getPageStart() + startIndex + childCount;

      TableRowElement insertBefore = table.getChildElement(startIndex).cast();
      if (table.legacyRenderRowValues) {
        int count = 0;
        while (insertBefore != null && count < childCount) {
          Element next = insertBefore.getNextSiblingElement();
          section.removeChild(insertBefore);
          insertBefore = (next == null) ? null : next.<TableRowElement> cast();
          count++;
        }
      } else {
        while (insertBefore != null
            && table.tableBuilder.getRowValueIndex(insertBefore) < absEndIndex) {
          Element next = insertBefore.getNextSiblingElement();
          section.removeChild(insertBefore);
          insertBefore = (next == null) ? null : next.<TableRowElement> cast();
        }
      }

      // Add new child elements.
      TableSectionElement newSection = convertToSectionElement(table, section.getTagName(), html);
      Element newChild = newSection.getFirstChildElement();
      while (newChild != null) {
        Element next = newChild.getNextSiblingElement();
        section.insertBefore(newChild, insertBefore);
        newChild = next;
      }

      /*
       * Reattach the section. If next section is null, the section will be
       * appended instead.
       */
      reattachSectionElement(parent, section, nextSection);

      // Detach the event listener.
      if (!table.isAttached()) {
        DOM.setEventListener(table.getElement(), null);
      }
    }

    /**
     * Detach a table section element from its parent.
     * 
     * @param section the element to detach
     */
    protected void detachSectionElement(TableSectionElement section) {
      section.removeFromParent();
    }

    /**
     * Reattach a table section element from its parent.
     * 
     * @param parent the parent element
     * @param section the element to reattach
     * @param nextSection the next section
     */
    protected void reattachSectionElement(Element parent, TableSectionElement section,
        Element nextSection) {
      parent.insertBefore(section, nextSection);
    }

    /**
     * Render a table section in the table.
     * 
     * @param table the {@link AbstractCellTable}
     * @param section the {@link TableSectionElement} to replace
     * @param html the html of a table section element containing the rows
     */
    protected void replaceAllRowsImpl(AbstractCellTable<?> table, TableSectionElement section,
        SafeHtml html) {
      section.setInnerSafeHtml(html);
    }
  }

  /**
   * Implementation of {@link CellTable} used by Firefox.
   */
  @SuppressWarnings("unused")
  private static class ImplMozilla extends Impl {
    /**
     * Firefox 3.6 and earlier convert td elements to divs if the tbody is
     * removed from the table element.
     */
    @Override
    protected void detachSectionElement(TableSectionElement section) {
      if (isGecko192OrBefore()) {
        return;
      }
      super.detachSectionElement(section);
    }

    @Override
    protected void reattachSectionElement(Element parent, TableSectionElement section,
        Element nextSection) {
      if (isGecko192OrBefore()) {
        return;
      }
      super.reattachSectionElement(parent, section, nextSection);
    }

    /**
     * Return true if using Gecko 1.9.2 (Firefox 3.6) or earlier.
     */
    private native boolean isGecko192OrBefore() /*-{
      return @com.google.gwt.dom.client.DOMImplMozilla::isGecko192OrBefore()();
    }-*/;
  }

  /**
   * Implementation of {@link AbstractCellTable} used by IE.
   */
  @SuppressWarnings("unused")
  private static class ImplTrident extends Impl {

    /**
     * A different optimization is used in IE.
     */
    @Override
    protected void detachSectionElement(TableSectionElement section) {
      return;
    }

    @Override
    protected void reattachSectionElement(Element parent, TableSectionElement section,
        Element nextSection) {
      return;
    }

    /**
     * Instead of replacing each TR element, swaping out the entire section is much faster. If
     * the table has a sectionChangeHandler, this method will be used.
     */
    @Override
    protected void replaceAllRowsImpl(AbstractCellTable<?> table, TableSectionElement section,
        SafeHtml html) {
      if (table instanceof TableSectionChangeHandler) {
        replaceTableSection(table, section, html);
      } else {
        replaceAllRowsImplLegacy(table, section, html);
      }
    }
    
    /**
     * This method is used for legacy AbstractCellTable that's not a
     * {@link TableSectionChangeHandler}.
     */
    protected void replaceAllRowsImplLegacy(AbstractCellTable<?> table, TableSectionElement section,
        SafeHtml html) {
      // Remove all children.
      Element child = section.getFirstChildElement();
      while (child != null) {
        Element next = child.getNextSiblingElement();
        section.removeChild(child);
        child = next;
      }

      // Add new child elements.
      TableSectionElement newSection = convertToSectionElement(table, section.getTagName(), html);
      child = newSection.getFirstChildElement();
      while (child != null) {
        Element next = child.getNextSiblingElement();
        section.appendChild(child);
        child = next;
      }
    }
    
    /**
     * Render html into a table section. This is achieved by first setting the html in a DIV
     * element, and then swap the table section with the corresponding element in the DIV. This
     * method is used in IE since the normal optimizations are not feasible.
     * 
     * @param table the {@link AbstractCellTable}
     * @param section the {@link TableSectionElement} to replace
     * @param html the html of a table section element containing the rows
     */
    private void replaceTableSection(AbstractCellTable<?> table, TableSectionElement section,
        SafeHtml html) {
      String sectionName = section.getTagName().toLowerCase();
      TableSectionElement newSection = convertToSectionElement(table, sectionName, html);
      TableElement tableElement = table.getElement().cast();
      tableElement.replaceChild(newSection, section);
      if ("tbody".equals(sectionName)) {
        ((TableSectionChangeHandler) table).onTableBodyChange(newSection);
      } else if ("thead".equals(sectionName)) {
        ((TableSectionChangeHandler) table).onTableHeadChange(newSection);
      } else if ("tfoot".equals(sectionName)) {
        ((TableSectionChangeHandler) table).onTableFootChange(newSection);
      }
    }
  }

  /**
   * The error message used when {@link HeaderBuilder} returns malformed table
   * section HTML.
   */
  private static final String MALFORMED_HTML_SECTION =
      "Malformed HTML: The table section returned by HeaderBuilder or FooterBuilder must use the "
          + "tag name thead or tfoot, as appropriate, and cannot contain any attributes or styles.";

  /*
   * The table specific {@link Impl}.
   */
  private static Impl TABLE_IMPL;

  private static Template template;

  /**
   * Check if a column consumes events.
   */
  private static boolean isColumnInteractive(HasCell<?, ?> column) {
    Set<String> consumedEvents = column.getCell().getConsumedEvents();
    return consumedEvents != null && consumedEvents.size() > 0;
  }

  /**
   * Get the {@link TableSectionElement} containing the children.
   * 
   * @param tag the expected tag (tbody, tfoot, or thead)
   */
  private static SafeHtml tableSectionToSafeHtml(TableSectionBuilder section, String tag) {
    if (!(section instanceof HtmlTableSectionBuilder)) {
      throw new IllegalArgumentException("Only HtmlTableSectionBuilder is supported at this time");
    }

    // Strip the table section tags off of the tbody.
    HtmlTableSectionBuilder htmlSection = (HtmlTableSectionBuilder) section;
    String rawHtml = htmlSection.asSafeHtml().asString();
    assert (tag.length()) == 5 : "Unrecognized tag: " + tag;
    assert rawHtml.startsWith("<" + tag + ">") : MALFORMED_HTML_SECTION;
    assert rawHtml.endsWith("</" + tag + ">") : MALFORMED_HTML_SECTION;
    rawHtml = rawHtml.substring(7, rawHtml.length() - 8);
    return SafeHtmlUtils.fromTrustedString(rawHtml);
  }

  private boolean cellIsEditing;
  private final List<Column<T, ?>> columns = new ArrayList<Column<T, ?>>();
  private final Map<Column<T, ?>, String> columnWidths = new HashMap<Column<T, ?>, String>();
  private boolean columnWidthsDirty;
  private final Map<Integer, String> columnWidthsByIndex = new HashMap<Integer, String>();

  /**
   * The maximum column index specified in column widths by index.
   */
  private int maxColumnIndex = -1;

  /**
   * Indicates that at least one column depends on selection.
   */
  private boolean dependsOnSelection;

  private Widget emptyTableWidget;
  private FooterBuilder<T> footerBuilder;
  private boolean footerRefreshDisabled;
  private final List<Header<?>> footers = new ArrayList<Header<?>>();

  /**
   * Indicates that at least one column handles selection.
   */
  private boolean handlesSelection;

  private HeaderBuilder<T> headerBuilder;
  private boolean headerRefreshDisabled;
  private final List<Header<?>> headers = new ArrayList<Header<?>>();

  /**
   * Indicates that either the headers or footers are dirty, and both should be
   * refreshed the next time the table is redrawn.
   */
  private boolean headersDirty;

  private TableRowElement hoveringRow;

  /**
   * Indicates that at least one column is interactive.
   */
  private boolean isInteractive;

  private int keyboardSelectedColumn = 0;
  private int keyboardSelectedSubrow = 0;
  private int lastKeyboardSelectedSubrow = 0;
  private Widget loadingIndicator;
  private boolean legacyRenderRowValues = true;
  private final Resources resources;
  private RowStyles<T> rowStyles;
  private final ColumnSortList sortList = new ColumnSortList(new ColumnSortList.Delegate() {
    @Override
    public void onModification() {
      if (!updatingSortList) {
        createHeaders(false);
      }
    }
  });
  private final Style style;
  private CellTableBuilder<T> tableBuilder;
  private boolean updatingSortList;

  private boolean skipRowHoverCheck;
  private boolean skipRowHoverFloatElementCheck;
  private boolean skipRowHoverStyleUpdate;

  /**
   * Constructs a table with the given page size, the specified {@link Style},
   * and the given key provider.
   * 
   * @param elem the parent {@link Element}
   * @param pageSize the page size
   * @param resources the resources to apply to the widget
   * @param keyProvider an instance of ProvidesKey<T>, or null if the record
   *          object should act as its own key
   */
  public AbstractCellTable(Element elem, final int pageSize, Resources resources,
      ProvidesKey<T> keyProvider) {
    super(elem, pageSize, keyProvider);
    this.resources = resources;
    this.style = resources.style();
    init();
  }

  /**
   * Constructs a table with the given page size, the specified {@link Style},
   * and the given key provider.
   * 
   * @param widget the parent widget
   * @param pageSize the page size
   * @param resources the resources to apply to the widget
   * @param keyProvider an instance of ProvidesKey<T>, or null if the record
   *          object should act as its own key
   */
  public AbstractCellTable(Widget widget, final int pageSize, Resources resources,
      ProvidesKey<T> keyProvider) {
    super(widget, pageSize, keyProvider);
    this.resources = resources;
    this.style = resources.style();
    init();
  }

  /**
   * Adds a column to the end of the table.
   * 
   * @param col the column to be added
   */
  public void addColumn(Column<T, ?> col) {
    insertColumn(getColumnCount(), col);
  }

  /**
   * Adds a column to the end of the table with an associated header.
   * 
   * @param col the column to be added
   * @param header the associated {@link Header}
   */
  public void addColumn(Column<T, ?> col, Header<?> header) {
    insertColumn(getColumnCount(), col, header);
  }

  /**
   * Adds a column to the end of the table with an associated header and footer.
   * 
   * @param col the column to be added
   * @param header the associated {@link Header}
   * @param footer the associated footer (as a {@link Header} object)
   */
  public void addColumn(Column<T, ?> col, Header<?> header, Header<?> footer) {
    insertColumn(getColumnCount(), col, header, footer);
  }

  /**
   * Adds a column to the end of the table with an associated String header.
   * 
   * @param col the column to be added
   * @param headerString the associated header text, as a String
   */
  public void addColumn(Column<T, ?> col, String headerString) {
    insertColumn(getColumnCount(), col, headerString);
  }

  /**
   * Adds a column to the end of the table with an associated {@link SafeHtml}
   * header.
   * 
   * @param col the column to be added
   * @param headerHtml the associated header text, as safe HTML
   */
  public void addColumn(Column<T, ?> col, SafeHtml headerHtml) {
    insertColumn(getColumnCount(), col, headerHtml);
  }

  /**
   * Adds a column to the end of the table with an associated String header and
   * footer.
   * 
   * @param col the column to be added
   * @param headerString the associated header text, as a String
   * @param footerString the associated footer text, as a String
   */
  public void addColumn(Column<T, ?> col, String headerString, String footerString) {
    insertColumn(getColumnCount(), col, headerString, footerString);
  }

  /**
   * Adds a column to the end of the table with an associated {@link SafeHtml}
   * header and footer.
   * 
   * @param col the column to be added
   * @param headerHtml the associated header text, as safe HTML
   * @param footerHtml the associated footer text, as safe HTML
   */
  public void addColumn(Column<T, ?> col, SafeHtml headerHtml, SafeHtml footerHtml) {
    insertColumn(getColumnCount(), col, headerHtml, footerHtml);
  }

  /**
   * Add a handler to handle {@link ColumnSortEvent}s.
   * 
   * @param handler the {@link ColumnSortEvent.Handler} to add
   * @return a {@link HandlerRegistration} to remove the handler
   */
  public HandlerRegistration addColumnSortHandler(ColumnSortEvent.Handler handler) {
    return addHandler(handler, ColumnSortEvent.getType());
  }

  /**
   * Add a style name to the <code>col</code> element at the specified index,
   * creating it if necessary.
   * 
   * @param index the column index
   * @param styleName the style name to add
   */
  public abstract void addColumnStyleName(int index, String styleName);
  
  /**
   * Add a handler to handle {@link RowHoverEvent}s.
   * 
   * @param handler the {@link RowHoverEvent.Handler} to add
   * @return a {@link HandlerRegistration} to remove the handler
   */
  public HandlerRegistration addRowHoverHandler(RowHoverEvent.Handler handler) {
    return addHandler(handler, RowHoverEvent.getType());
  }

  /**
   * Clear the width of the specified {@link Column}.
   * 
   * @param column the column
   */
  public void clearColumnWidth(Column<T, ?> column) {
    columnWidths.remove(column);
    updateColumnWidthImpl(column, null);
  }

  /**
   * Clear the width of the specified {@link Column}.
   * 
   * @param column the column index
   */
  public void clearColumnWidth(Integer column) {
    columnWidthsByIndex.remove(column);

    // Recalculate the maximum column index.
    if (column >= maxColumnIndex) {
      maxColumnIndex = -1;
      for (Integer index : columnWidthsByIndex.keySet()) {
        maxColumnIndex = Math.max(maxColumnIndex, index);
      }
    }

    // Update the width of the column.
    if (column < getRealColumnCount()) {
      doSetColumnWidth(column, null);
    }
  }

  /**
   * Flush all pending changes to the table and render immediately.
   * 
   * <p>
   * Modifications to the table, such as adding columns or setting data, are not
   * rendered immediately. Instead, changes are coalesced at the end of the
   * current event loop to avoid rendering the table multiple times. Use this
   * method to force the table to render all pending modifications immediately.
   * </p>
   */
  public void flush() {
    getPresenter().flush();
  }

  /**
   * Get the column at the specified index.
   * 
   * @param col the index of the column to retrieve
   * @return the {@link Column} at the index
   */
  public Column<T, ?> getColumn(int col) {
    checkColumnBounds(col);
    return columns.get(col);
  }

  /**
   * Get the number of columns in the table.
   * 
   * @return the column count
   */
  public int getColumnCount() {
    return columns.size();
  }

  /**
   * Get the index of the specified column.
   * 
   * @param column the column to search for
   * @return the index of the column, or -1 if not found
   */
  public int getColumnIndex(Column<T, ?> column) {
    return columns.indexOf(column);
  }

  /**
   * Get the {@link ColumnSortList} that specifies which columns are sorted.
   * Modifications to the {@link ColumnSortList} will be reflected in the table
   * header.
   * 
   * <p>
   * Note that the implementation may redraw the headers on every modification
   * to the {@link ColumnSortList}.
   * </p>
   * 
   * @return the {@link ColumnSortList}
   */
  public ColumnSortList getColumnSortList() {
    return sortList;
  }

  /**
   * Get the width of a {@link Column}.
   * 
   * @param column the column
   * @return the width of the column, or null if not set
   * @see #setColumnWidth(Column, double, Unit)
   */
  public String getColumnWidth(Column<T, ?> column) {
    return columnWidths.get(column);
  }

  /**
   * Get the widget displayed when the table has no rows.
   * 
   * @return the empty table widget
   */
  public Widget getEmptyTableWidget() {
    return emptyTableWidget;
  }

  /**
   * Get the {@link Header} from the footer section that was added with a
   * {@link Column}.
   */
  public Header<?> getFooter(int index) {
    return footers.get(index);
  }

  /**
   * Get the {@link HeaderBuilder} used to generate the footer section.
   */
  public FooterBuilder<T> getFooterBuilder() {
    return footerBuilder;
  }

  /**
   * Get the {@link Header} from the header section that was added with a
   * {@link Column}.
   */
  public Header<?> getHeader(int index) {
    return headers.get(index);
  }

  /**
   * Get the {@link HeaderBuilder} used to generate the header section.
   */
  public HeaderBuilder<T> getHeaderBuilder() {
    return headerBuilder;
  }

  /**
   * Get the index of the column that is currently selected via the keyboard.
   * 
   * @return the currently selected column, or -1 if none selected
   */
  public int getKeyboardSelectedColumn() {
    return KeyboardSelectionPolicy.DISABLED == getKeyboardSelectionPolicy() ? -1
        : keyboardSelectedColumn;
  }

  /**
   * Get the index of the sub row that is currently selected via the keyboard.
   * If the row value maps to one rendered row element, the subrow is 0.
   * 
   * @return the currently selected subrow, or -1 if none selected
   */
  public int getKeyboardSelectedSubRow() {
    return KeyboardSelectionPolicy.DISABLED == getKeyboardSelectionPolicy() ? -1
        : keyboardSelectedSubrow;
  }

  /**
   * Get the widget displayed when the data is loading.
   * 
   * @return the loading indicator
   */
  public Widget getLoadingIndicator() {
    return loadingIndicator;
  }

  /**
   * Get the resources used by this table.
   */
  public Resources getResources() {
    return resources;
  }

  /**
   * Get the {@link TableRowElement} for the specified row. If the row element
   * has not been created, null is returned.
   * 
   * @param row the row index
   * @return the row element, or null if it doesn't exists
   * @throws IndexOutOfBoundsException if the row index is outside of the
   *           current page
   */
  public TableRowElement getRowElement(int row) {
    flush();
    return getChildElement(row);
  }

  /**
   * Gets the object used to determine how a row is styled.
   * 
   * @return the {@link RowStyles} object if set, null if not
   */
  public RowStyles<T> getRowStyles() {
    return this.rowStyles;
  }

  /**
   * Inserts a column into the table at the specified index.
   * 
   * @param beforeIndex the index to insert the column
   * @param col the column to be added
   */
  public void insertColumn(int beforeIndex, Column<T, ?> col) {
    insertColumn(beforeIndex, col, (Header<?>) null, (Header<?>) null);
  }

  /**
   * Inserts a column into the table at the specified index with an associated
   * header.
   * 
   * @param beforeIndex the index to insert the column
   * @param col the column to be added
   * @param header the associated {@link Header}
   */
  public void insertColumn(int beforeIndex, Column<T, ?> col, Header<?> header) {
    insertColumn(beforeIndex, col, header, null);
  }

  /**
   * Inserts a column into the table at the specified index with an associated
   * header and footer.
   * 
   * @param beforeIndex the index to insert the column
   * @param col the column to be added
   * @param header the associated {@link Header}
   * @param footer the associated footer (as a {@link Header} object)
   * @throws IndexOutOfBoundsException if the index is out of range
   */
  public void insertColumn(int beforeIndex, Column<T, ?> col, Header<?> header, Header<?> footer) {
    // Allow insert at the end.
    if (beforeIndex != getColumnCount()) {
      checkColumnBounds(beforeIndex);
    }

    headers.add(beforeIndex, header);
    footers.add(beforeIndex, footer);
    columns.add(beforeIndex, col);

    // Increment the keyboard selected column.
    if (beforeIndex <= keyboardSelectedColumn) {
      keyboardSelectedColumn = Math.min(keyboardSelectedColumn + 1, columns.size() - 1);
    }

    // Move the keyboard selected column if the current column is not
    // interactive.
    if (isColumnInteractive(col)
        && ((keyboardSelectedColumn >= columns.size()) || !isColumnInteractive(columns
            .get(keyboardSelectedColumn)))) {
      keyboardSelectedColumn = beforeIndex;
    }

    // Sink events used by the new column.
    Set<String> consumedEvents = new HashSet<String>();
    {
      Set<String> cellEvents = col.getCell().getConsumedEvents();
      if (cellEvents != null) {
        consumedEvents.addAll(cellEvents);
      }
    }
    if (header != null) {
      Set<String> headerEvents = header.getCell().getConsumedEvents();
      if (headerEvents != null) {
        consumedEvents.addAll(headerEvents);
      }
    }
    if (footer != null) {
      Set<String> footerEvents = footer.getCell().getConsumedEvents();
      if (footerEvents != null) {
        consumedEvents.addAll(footerEvents);
      }
    }
    CellBasedWidgetImpl.get().sinkEvents(this, consumedEvents);

    headersDirty = true;
    refreshColumnsAndRedraw();
  }

  /**
   * Inserts a column into the table at the specified index with an associated
   * String header.
   * 
   * @param beforeIndex the index to insert the column
   * @param col the column to be added
   * @param headerString the associated header text, as a String
   */
  public void insertColumn(int beforeIndex, Column<T, ?> col, String headerString) {
    insertColumn(beforeIndex, col, new TextHeader(headerString), null);
  }

  /**
   * Inserts a column into the table at the specified index with an associated
   * {@link SafeHtml} header.
   * 
   * @param beforeIndex the index to insert the column
   * @param col the column to be added
   * @param headerHtml the associated header text, as safe HTML
   */
  public void insertColumn(int beforeIndex, Column<T, ?> col, SafeHtml headerHtml) {
    insertColumn(beforeIndex, col, new SafeHtmlHeader(headerHtml), null);
  }

  /**
   * Inserts a column into the table at the specified index with an associated
   * String header and footer.
   * 
   * @param beforeIndex the index to insert the column
   * @param col the column to be added
   * @param headerString the associated header text, as a String
   * @param footerString the associated footer text, as a String
   */
  public void insertColumn(int beforeIndex, Column<T, ?> col, String headerString,
      String footerString) {
    insertColumn(beforeIndex, col, new TextHeader(headerString), new TextHeader(footerString));
  }

  /**
   * Inserts a column into the table at the specified index with an associated
   * {@link SafeHtml} header and footer.
   * 
   * @param beforeIndex the index to insert the column
   * @param col the column to be added
   * @param headerHtml the associated header text, as safe HTML
   * @param footerHtml the associated footer text, as safe HTML
   */
  public void insertColumn(int beforeIndex, Column<T, ?> col, SafeHtml headerHtml,
      SafeHtml footerHtml) {
    insertColumn(beforeIndex, col, new SafeHtmlHeader(headerHtml), new SafeHtmlHeader(footerHtml));
  }

  /**
   * Check if auto footer refresh is enabled or disabled.
   * 
   * @return true if disabled, false if enabled
   * @see #setAutoFooterRefreshDisabled(boolean)
   */
  public boolean isAutoFooterRefreshDisabled() {
    return footerRefreshDisabled;
  }

  /**
   * Check if auto header refresh is enabled or disabled.
   * 
   * @return true if disabled, false if enabled
   * @see #setAutoHeaderRefreshDisabled(boolean)
   */
  public boolean isAutoHeaderRefreshDisabled() {
    return headerRefreshDisabled;
  }

  /**
   * Gets the skipRowHoverCheck flag. If true, the CellTable will not check for
   * row-level hover events (MOUSEOVER and MOUSEOUT).
   *
   * @return the flag value
   */
  public boolean isSkipRowHoverCheck() {
    return this.skipRowHoverCheck;
  }

  /**
   * Gets the skipRowHoverFloatElementCheck flag. If true, the CellTable will
   * not check for floating (fixed position) elements over the hovered row.
   *
   * @return the flag value
   */
  public boolean isSkipRowHoverFloatElementCheck() {
    return this.skipRowHoverFloatElementCheck;
  }

  /**
   * Gets the skipRowHoverStyleUpdate flag. If true, the CellTable will not update
   * the row's style on row-level hover events (MOUSEOVER and MOUSEOUT).
   *
   * @return the flag value
   */
  public boolean isSkipRowHoverStyleUpdate() {
    return this.skipRowHoverStyleUpdate;
  }

  /**
   * Redraw the table's footers. The footers will be re-rendered synchronously.
   */
  public void redrawFooters() {
    createHeaders(true);
  }

  /**
   * Redraw the table's headers. The headers will be re-rendered synchronously.
   */
  public void redrawHeaders() {
    createHeaders(false);
  }

  /**
   * Remove a column.
   * 
   * @param col the column to remove
   */
  public void removeColumn(Column<T, ?> col) {
    int index = columns.indexOf(col);
    if (index < 0) {
      throw new IllegalArgumentException("The specified column is not part of this table.");
    }
    removeColumn(index);
  }

  /**
   * Remove a column.
   * 
   * @param index the column index
   */
  public void removeColumn(int index) {
    if (index < 0 || index >= columns.size()) {
      throw new IndexOutOfBoundsException("The specified column index is out of bounds.");
    }
    columns.remove(index);
    headers.remove(index);
    footers.remove(index);

    // Decrement the keyboard selected column.
    if (index <= keyboardSelectedColumn && keyboardSelectedColumn > 0) {
      keyboardSelectedColumn--;
    }

    // Redraw the table asynchronously.
    headersDirty = true;
    refreshColumnsAndRedraw();

    // We don't unsink events because other handlers or user code may have sunk
    // them intentionally.
  }

  /**
   * Remove a style from the <code>col</code> element at the specified index.
   * 
   * @param index the column index
   * @param styleName the style name to remove
   */
  public abstract void removeColumnStyleName(int index, String styleName);

  /**
   * Enable or disable auto footer refresh when row data is changed. By default,
   * footers are refreshed every time the row data changes in case the headers
   * depend on the current row data. If the headers do not depend on the current
   * row data, you can disable this feature to improve performance.
   * 
   * <p>
   * Note that headers will still refresh when columns are added or removed,
   * regardless of whether or not this feature is enabled.
   * </p>
   */
  public void setAutoFooterRefreshDisabled(boolean disabled) {
    this.footerRefreshDisabled = disabled;
  }

  /**
   * Enable or disable auto header refresh when row data is changed. By default,
   * headers are refreshed every time the row data changes in case the footers
   * depend on the current row data. If the footers do not depend on the current
   * row data, you can disable this feature to improve performance.
   * 
   * <p>
   * Note that footers will still refresh when columns are added or removed,
   * regardless of whether or not this feature is enabled.
   * </p>
   */
  public void setAutoHeaderRefreshDisabled(boolean disabled) {
    this.headerRefreshDisabled = disabled;
  }

  /**
   * Set the width of a {@link Column}. The width will persist with the column
   * and takes precedence of any width set via
   * {@link #setColumnWidth(int, String)}.
   * 
   * @param column the column
   * @param width the width of the column
   */
  public void setColumnWidth(Column<T, ?> column, String width) {
    columnWidths.put(column, width);
    updateColumnWidthImpl(column, width);
  }

  /**
   * Set the width of a {@link Column}. The width will persist with the column
   * and takes precedence of any width set via
   * {@link #setColumnWidth(int, double, Unit)}.
   * 
   * @param column the column
   * @param width the width of the column
   * @param unit the {@link Unit} of measurement
   */
  public void setColumnWidth(Column<T, ?> column, double width, Unit unit) {
    setColumnWidth(column, width + unit.getType());
  }

  /**
   * Set the width of a {@link Column}.
   * 
   * @param column the column
   * @param width the width of the column
   * @param unit the {@link Unit} of measurement
   */
  public void setColumnWidth(int column, double width, Unit unit) {
    setColumnWidth(column, width + unit.getType());
  }

  /**
   * Set the width of a {@link Column}.
   * 
   * @param column the column
   * @param width the width of the column
   */
  public void setColumnWidth(int column, String width) {
    columnWidthsByIndex.put(column, width);
    maxColumnIndex = Math.max(maxColumnIndex, column);

    // Update the column width.
    if (column < getRealColumnCount()) {
      doSetColumnWidth(column, width);
    }
  }

  /**
   * Set the widget to display when the table has no rows.
   * 
   * @param widget the empty table widget, or null to disable
   */
  public void setEmptyTableWidget(Widget widget) {
    this.emptyTableWidget = widget;
  }

  /**
   * Set the {@link HeaderBuilder} used to build the footer section of the
   * table.
   */
  public void setFooterBuilder(FooterBuilder<T> builder) {
    assert builder != null : "builder cannot be null";
    this.footerBuilder = builder;
    redrawFooters();
  }

  /**
   * Set the {@link HeaderBuilder} used to build the header section of the
   * table.
   */
  public void setHeaderBuilder(HeaderBuilder<T> builder) {
    assert builder != null : "builder cannot be null";
    this.headerBuilder = builder;
    redrawHeaders();
  }

  /**
   * Set the keyboard selected column index.
   * 
   * <p>
   * If keyboard selection is disabled, this method does nothing.
   * </p>
   * 
   * <p>
   * If the keyboard selected column is greater than the number of columns in
   * the keyboard selected row, the last column in the row is selected, but the
   * column index is remembered.
   * </p>
   * 
   * @param column the column index, greater than or equal to zero
   */
  public final void setKeyboardSelectedColumn(int column) {
    setKeyboardSelectedColumn(column, true);
  }

  /**
   * Set the keyboard selected column index and optionally focus on the new
   * cell.
   * 
   * @param column the column index, greater than or equal to zero
   * @param stealFocus true to focus on the new column
   * @see #setKeyboardSelectedColumn(int)
   */
  public void setKeyboardSelectedColumn(int column, boolean stealFocus) {
    assert column >= 0 : "Column must be zero or greater";
    if (KeyboardSelectionPolicy.DISABLED == getKeyboardSelectionPolicy()) {
      return;
    }

    this.keyboardSelectedColumn = column;

    // Reselect the row to move the selected column.
    setKeyboardSelectedRow(getKeyboardSelectedRow(), keyboardSelectedSubrow, stealFocus);
  }

  @Override
  public void setKeyboardSelectedRow(int row, boolean stealFocus) {
    setKeyboardSelectedRow(row, 0, stealFocus);
  }

  /**
   * Set the keyboard selected row and subrow, optionally focus on the new row.
   * 
   * @param row the row index relative to the page start
   * @param subrow the row index of the child row
   * @param stealFocus true to focus on the new row
   * @see #setKeyboardSelectedRow(int)
   */
  public void setKeyboardSelectedRow(int row, int subrow, boolean stealFocus) {
    this.keyboardSelectedSubrow = subrow;
    super.setKeyboardSelectedRow(row, stealFocus);
  }

  /**
   * Set the widget to display when the data is loading.
   * 
   * @param widget the loading indicator, or null to disable
   */
  public void setLoadingIndicator(Widget widget) {
    loadingIndicator = widget;
  }

  /**
   * Sets the object used to determine how a row is styled; the change will take
   * effect the next time that the table is rendered.
   * 
   * @param rowStyles a {@link RowStyles} object
   */
  public void setRowStyles(RowStyles<T> rowStyles) {
    this.rowStyles = rowStyles;
  }

  /**
   * Sets the skipRowHoverCheck flag. If set, the CellTable will not check for
   * row-level hover events (MOUSEOVER and MOUSEOUT).
   *
   * @param skipRowHoverCheck the new flag value
   */
  public void setSkipRowHoverCheck(boolean skipRowHoverCheck) {
    this.skipRowHoverCheck = skipRowHoverCheck;
  }

  /**
   * Sets the skipRowHoverFloatElementCheck flag. If set, the CellTable will not
   * not check for floating (fixed position) elements over the hovered row.
   *
   * @param skipRowHoverFloatElementCheck the new flag value
   */
  public void setSkipRowHoverFloatElementCheck(boolean skipRowHoverFloatElementCheck) {
    this.skipRowHoverFloatElementCheck = skipRowHoverFloatElementCheck;
  }

  /**
   * Sets the skipRowHoverStyleUpdate flag. If set, the CellTable will not update
   * the row's style on row-level hover events (MOUSEOVER and MOUSEOUT).
   *
   * @param skipRowHoverCheck the new flag value
   */
  public void setSkipRowHoverStyleUpdate(boolean skipRowHoverStyleUpdate) {
    this.skipRowHoverStyleUpdate = skipRowHoverStyleUpdate;
  }

  /**
   * Specify the {@link CellTableBuilder} that will be used to render the row
   * values into the table.
   */
  public void setTableBuilder(CellTableBuilder<T> tableBuilder) {
    assert tableBuilder != null : "tableBuilder cannot be null";
    this.tableBuilder = tableBuilder;
    redraw();
  }

  @Override
  protected Element convertToElements(SafeHtml html) {
    return TABLE_IMPL.convertToSectionElement(AbstractCellTable.this, "tbody", html);
  }

  @Override
  protected boolean dependsOnSelection() {
    return dependsOnSelection;
  }

  /**
   * Set the width of a column.
   * 
   * @param column the column index
   * @param width the width, or null to clear the width
   */
  protected abstract void doSetColumnWidth(int column, String width);

  /**
   * Show or hide a header section.
   * 
   * @param isFooter true for the footer, false for the header
   * @param isVisible true to show, false to hide
   */
  protected abstract void doSetHeaderVisible(boolean isFooter, boolean isVisible);

  @Override
  protected Element getChildContainer() {
    return getTableBodyElement();
  }

  /**
   * {@inheritDoc}
   * 
   * <p>
   * The row element may not be the same as the TR element at the specified
   * index if some row values are rendered with additional rows.
   * </p>
   * 
   * @param row the row index, relative to the page start
   * @return the row element, or null if it doesn't exists
   * @throws IndexOutOfBoundsException if the row index is outside of the
   *           current page
   */
  @Override
  protected TableRowElement getChildElement(int row) {
    return getSubRowElement(row + getPageStart(), 0);
  }

  @Override
  protected Element getKeyboardSelectedElement() {
    return getKeyboardSelectedElement(getKeyboardSelectedTableCellElement());
  }

  /**
   * Get the real column count, which is the greater of the number of Columns or
   * the maximum index of a column with a defined column width.
   */
  protected int getRealColumnCount() {
    return Math.max(getColumnCount(), maxColumnIndex + 1);
  }

  /**
   * Get the tbody element that contains the render row values.
   */
  protected abstract TableSectionElement getTableBodyElement();

  /**
   * Get the tfoot element that contains the footers.
   */
  protected abstract TableSectionElement getTableFootElement();

  /**
   * Get the thead element that contains the headers.
   */
  protected abstract TableSectionElement getTableHeadElement();

  @Override
  protected boolean isKeyboardNavigationSuppressed() {
    return cellIsEditing;
  }

  @Override
  protected void onBlur() {
    TableCellElement td = getKeyboardSelectedTableCellElement();
    if (td != null) {
      TableRowElement tr = td.getParentElement().cast();
      td.removeClassName(style.keyboardSelectedCell());
      setRowStyleName(tr, style.keyboardSelectedRow(), style.keyboardSelectedRowCell(), false);
    }
  }

  @SuppressWarnings("deprecation")
  @Override
  protected void onBrowserEvent2(Event event) {
    // Get the event target.
    EventTarget eventTarget = event.getEventTarget();
    if (!Element.is(eventTarget)) {
      return;
    }
    final Element target = event.getEventTarget().cast();

    // Find the cell where the event occurred.
    TableSectionElement tbody = getTableBodyElement();
    TableSectionElement tfoot = getTableFootElement();
    TableSectionElement thead = getTableHeadElement();
    TableSectionElement targetTableSection = null;
    TableCellElement targetTableCell = null;
    Element cellParent = null;
    Element headerParent = null; // Header in the headerBuilder.
    Element headerColumnParent = null; // Column in the headerBuilder.
    Element footerParent = null; // Header in the footerBuilder.
    Element footerColumnParent = null; // Column in the footerBuilder.
    {
      Element maybeTableCell = null;
      Element cur = target;
      while (cur != null && targetTableSection == null) {
        /*
         * Found the table section. Return the most recent cell element that we
         * discovered.
         */
        if (cur == tbody || cur == tfoot || cur == thead) {
          targetTableSection = cur.cast(); // We found the table section.
          if (maybeTableCell != null) {
            targetTableCell = maybeTableCell.cast();
            break;
          }
        }

        // Look for a table cell.
        String tagName = cur.getTagName();
        if (TableCellElement.TAG_TD.equalsIgnoreCase(tagName)
            || TableCellElement.TAG_TH.equalsIgnoreCase(tagName)) {
          /*
           * Found a table cell, but we can't return yet because it may be part
           * of a sub table within the a CellTable cell.
           */
          maybeTableCell = cur;
        }

        // Look for the most immediate cell parent if not already found.
        if (cellParent == null && tableBuilder.isColumn(cur)) {
          cellParent = cur;
        }

        /*
         * Look for the most immediate header parent if not already found. Its
         * possible that the footer or header will mistakenly identify a header
         * from the other section, so we remember both. When we eventually reach
         * the target table section element, we'll know for sure if its a header
         * of footer.
         */
        if (headerParent == null && headerBuilder.isHeader(cur)) {
          headerParent = cur;
        }
        if (footerParent == null && footerBuilder.isHeader(cur)) {
          footerParent = cur;
        }

        // Look for the most immediate column parent if not already found.
        if (headerColumnParent == null && headerBuilder.isColumn(cur)) {
          headerColumnParent = cur;
        }
        if (footerColumnParent == null && footerBuilder.isColumn(cur)) {
          footerColumnParent = cur;
        }

        // Iterate.
        cur = cur.getParentElement();
      }
    }
    if (targetTableCell == null) {
      return;
    }

    // Support the legacy mode where the div inside of the TD is the cell
    // parent.
    if (legacyRenderRowValues) {
      cellParent = targetTableCell.getFirstChildElement();
    }

    /*
     * Forward the event to the associated header, footer, or column.
     */
    TableRowElement targetTableRow = targetTableCell.getParentElement().cast();
    String eventType = event.getType();
    boolean isSelect = BrowserEvents.CLICK.equals(eventType)
        || (BrowserEvents.KEYDOWN.equals(eventType) && event.getKeyCode() == KeyCodes.KEY_ENTER);

    int col = targetTableCell.getCellIndex();
    if (targetTableSection == thead || targetTableSection == tfoot) {
      boolean isHeader = (targetTableSection == thead);
      headerParent = isHeader ? headerParent : footerParent;
      Element columnParent = isHeader ? headerColumnParent : footerColumnParent;

      boolean shouldSortColumn = true;
      // Fire the event to the header.
      if (headerParent != null) {
        Header<?> header =
            isHeader ? headerBuilder.getHeader(headerParent) : footerBuilder
                .getHeader(footerParent);

        if (header != null) {
          int headerIndex = isHeader ? headerBuilder.getRowIndex(targetTableRow) :
              footerBuilder.getRowIndex(targetTableRow);
          Context context = new Context(headerIndex, col, header.getKey());

          if (cellConsumesEventType(header.getCell(), eventType)) {          
            header.onBrowserEvent(context, headerParent, event);
          }

          if (isSelect) {
            // Preview the event, and possibily disable the column sort event. The event preview is
            // forced even if the header cell does not consume click event
            shouldSortColumn = header.onPreviewColumnSortEvent(context, headerParent, event);
          }
        }
      }

      // Sort the header.
      if (isSelect && shouldSortColumn && columnParent != null) {
        Column<T, ?> column =
            isHeader ? headerBuilder.getColumn(columnParent) : footerBuilder
                .getColumn(columnParent);
        if (column != null && column.isSortable()) {
          /*
           * Force the headers to refresh the next time data is pushed so we
           * update the sort icon in the header.
           */
          headersDirty = true;

          updatingSortList = true;
          sortList.push(column);
          updatingSortList = false;
          ColumnSortEvent.fire(this, sortList);
        }
      }
    } else if (targetTableSection == tbody) {
      /*
       * Get the row index of the data value. This may not correspond to the DOM
       * row index if the user specifies multiple table rows per row object.
       */
      int absRow = tableBuilder.getRowValueIndex(targetTableRow);
      int relRow = absRow - getPageStart();
      int subrow = tableBuilder.getSubrowValueIndex(targetTableRow);

      if (!skipRowHoverCheck) {
        boolean isRowChange = hoveringRow != targetTableRow;
        if (BrowserEvents.MOUSEOVER.equals(eventType)) {
          // Unstyle the old row if it is still part of the table.
          if (hoveringRow != null && getTableBodyElement().isOrHasChild(hoveringRow)) {
            setRowHover(hoveringRow, event, false, isRowChange);
          }
          hoveringRow = targetTableRow;
          setRowHover(hoveringRow, event, true, isRowChange);
        } else if (BrowserEvents.MOUSEOUT.equals(eventType) && hoveringRow != null) {
          boolean unhover = true;
          if (!skipRowHoverFloatElementCheck) {
            // Ignore events happening directly over the hovering row. If there are floating element
            // on top of the row, mouseout event should not be triggered. This is to avoid the flickring
            // effect if the floating element is shown/hide based on hover event.
            int clientX = event.getClientX() + Window.getScrollLeft();
            int clientY = event.getClientY() + Window.getScrollTop();
            int rowLeft = hoveringRow.getAbsoluteLeft();
            int rowTop = hoveringRow.getAbsoluteTop();
            int rowWidth = hoveringRow.getOffsetWidth();
            int rowHeight = hoveringRow.getOffsetHeight();
            int rowBottom = rowTop + rowHeight;
            int rowRight = rowLeft + rowWidth;
            unhover = clientX < rowLeft || clientX > rowRight || clientY < rowTop || clientY > rowBottom;
          }
          if (unhover) {
            setRowHover(hoveringRow, event, false, isRowChange);
            hoveringRow = null;
          }
        }
      }

      // If the event causes us to page, then the physical index will be out
      // of bounds of the underlying data.
      if (!isRowWithinBounds(relRow)) {
        return;
      }

      /*
       * Fire a preview event. The preview event is fired even if the TD does
       * not contain a cell so the selection handler and keyboard handler have a
       * chance to act.
       */
      boolean isSelectionHandled =
          handlesSelection
              || KeyboardSelectionPolicy.BOUND_TO_SELECTION == getKeyboardSelectionPolicy();
      T value = getVisibleItem(relRow);

      /*
       * Create a new context based on the dom column index instead of using the
       * user provided one from TableBuilder. We trigger cell preview events for
       * table cells even if there is no associated Cell instance. If we used
       * the user provided context, we could get inconsistent states where the
       * Context is sometimes user provided and sometimes generated based on the
       * DOM column index.
       */
      Context context = new Context(absRow, col, getValueKey(value), subrow);
      CellPreviewEvent<T> previewEvent =
          CellPreviewEvent.fire(this, event, this, context, value, cellIsEditing,
              isSelectionHandled);

      // Pass the event to the cell.
      if (cellParent != null && !previewEvent.isCanceled()) {
        HasCell<T, ?> column;
        if (legacyRenderRowValues) {
          column = columns.get(col);
        } else {
          column = tableBuilder.getColumn(context, value, cellParent);
        }
        if (column != null) {
          fireEventToCell(event, eventType, cellParent, value, context, column);
        }
      }
    }
  }
  
  @Override
  protected void onFocus() {
    TableCellElement td = getKeyboardSelectedTableCellElement();
    if (td != null) {
      TableRowElement tr = td.getParentElement().cast();
      td.addClassName(style.keyboardSelectedCell());
      setRowStyleName(tr, style.keyboardSelectedRow(), style.keyboardSelectedRowCell(), true);
    }
  }

  protected void refreshColumnWidths() {
    int columnCount = getRealColumnCount();
    for (int i = 0; i < columnCount; i++) {
      doSetColumnWidth(i, getColumnWidth(i));
    }
  }

  /**
   * Throws an {@link UnsupportedOperationException}.
   * 
   * @deprecated as of GWT 2.5, use a {@link CellTableBuilder} to customize the
   *             table structure instead
   * @see #renderRowValuesLegacy(SafeHtmlBuilder, List, int, SelectionModel)
   */
  @Override
  @Deprecated
  protected void renderRowValues(SafeHtmlBuilder sb, List<T> values, int start,
      SelectionModel<? super T> selectionModel) {
    legacyRenderRowValues = false;
    throw new UnsupportedOperationException();
  }

  /**
   * Render all row values into the specified {@link SafeHtmlBuilder}.
   * 
   * <p>
   * This method is here for legacy reasons, to support subclasses that call
   * {@link #renderRowValues(SafeHtmlBuilder, List, int, SelectionModel)}.
   * </p>
   * 
   * @param sb the {@link SafeHtmlBuilder} to render into
   * @param values the row values
   * @param start the absolute start index of the values
   * @param selectionModel the {@link SelectionModel}
   * @deprecated as of GWT 2.5, use a {@link CellTableBuilder} to customize the
   *             table structure instead
   */
  @Deprecated
  protected final void renderRowValuesLegacy(SafeHtmlBuilder sb, List<T> values, int start,
      SelectionModel<? super T> selectionModel) {
    int keyboardSelectedRow = getKeyboardSelectedRow() + getPageStart();
    String evenRowStyle = style.evenRow();
    String oddRowStyle = style.oddRow();
    String cellStyle = style.cell();
    String evenCellStyle = " " + style.evenRowCell();
    String oddCellStyle = " " + style.oddRowCell();
    String firstColumnStyle = " " + style.firstColumn();
    String lastColumnStyle = " " + style.lastColumn();
    String selectedRowStyle = " " + style.selectedRow();
    String selectedCellStyle = " " + style.selectedRowCell();
    int columnCount = columns.size();
    int length = values.size();
    int end = start + length;
    for (int i = start; i < end; i++) {
      T value = values.get(i - start);
      boolean isSelected =
          (selectionModel == null || value == null) ? false : selectionModel.isSelected(value);
      boolean isEven = i % 2 == 0;
      String trClasses = isEven ? evenRowStyle : oddRowStyle;
      if (isSelected) {
        trClasses += selectedRowStyle;
      }

      if (rowStyles != null) {
        String extraRowStyles = rowStyles.getStyleNames(value, i);
        if (extraRowStyles != null) {
          trClasses += " ";
          trClasses += extraRowStyles;
        }
      }

      SafeHtmlBuilder trBuilder = new SafeHtmlBuilder();
      int curColumn = 0;
      for (Column<T, ?> column : columns) {
        String tdClasses = cellStyle;
        tdClasses += isEven ? evenCellStyle : oddCellStyle;
        if (curColumn == 0) {
          tdClasses += firstColumnStyle;
        }
        if (isSelected) {
          tdClasses += selectedCellStyle;
        }
        // The first and last column could be the same column.
        if (curColumn == columnCount - 1) {
          tdClasses += lastColumnStyle;
        }

        // Add class names specific to the cell.
        Context context = new Context(i, curColumn, getValueKey(value));
        String cellStyles = column.getCellStyleNames(context, value);
        if (cellStyles != null) {
          tdClasses += " " + cellStyles;
        }

        SafeHtmlBuilder cellBuilder = new SafeHtmlBuilder();
        if (value != null) {
          column.render(context, value, cellBuilder);
        }

        // Build the contents.
        SafeHtml contents = SafeHtmlUtils.EMPTY_SAFE_HTML;
        contents = template.div(cellBuilder.toSafeHtml());

        // Build the cell.
        HorizontalAlignmentConstant hAlign = column.getHorizontalAlignment();
        VerticalAlignmentConstant vAlign = column.getVerticalAlignment();
        if (hAlign != null && vAlign != null) {
          trBuilder.append(template.tdBothAlign(tdClasses, hAlign.getTextAlignString(), vAlign
              .getVerticalAlignString(), contents));
        } else if (hAlign != null) {
          trBuilder.append(template.tdHorizontalAlign(tdClasses, hAlign.getTextAlignString(),
              contents));
        } else if (vAlign != null) {
          trBuilder.append(template.tdVerticalAlign(tdClasses, vAlign.getVerticalAlignString(),
              contents));
        } else {
          trBuilder.append(template.td(tdClasses, contents));
        }

        curColumn++;
      }

      sb.append(template.tr(trClasses, trBuilder.toSafeHtml()));
    }
  }

  @Override
  protected void replaceAllChildren(List<T> values, SafeHtml html) {
    refreshHeadersAndColumnsImpl();

    /*
     * If html is not null, then the user overrode renderRowValues() and
     * rendered directly into a SafeHtmlBuilder. The legacy method is deprecated
     * but still supported.
     */
    if (html == null) {
      html = buildRowValues(values, getPageStart(), true);
    }

    TABLE_IMPL.replaceAllRows(this, getTableBodyElement(), CellBasedWidgetImpl.get().processHtml(
        html));
  }

  @SuppressWarnings("deprecation")
  @Override
  protected void replaceChildren(List<T> values, int start, SafeHtml html) {
    refreshHeadersAndColumnsImpl();

    /*
     * If html is not null, then the user override renderRowValues() and
     * rendered directly into a SafeHtmlBuilder. The legacy method is deprecated
     * but still supported.
     */
    if (html == null) {
      html = buildRowValues(values, getPageStart() + start, false);
    }

    TABLE_IMPL.replaceChildren(this, getTableBodyElement(), CellBasedWidgetImpl.get().processHtml(
        html), start, values.size());
  }

  @Override
  protected boolean resetFocusOnCell() {
    Element elem = getKeyboardSelectedElement();
    if (elem == null) {
      // There is no selected element.
      return false;
    }

    int row = getKeyboardSelectedRow();
    int col = getKeyboardSelectedColumn();
    T value = getVisibleItem(row);
    Object key = getValueKey(value);
    // TODO(pengzhuang): this doesn't support sub row selection?
    Context context = new Context(row + getPageStart(), col, key);
    HasCell<T, ?> column = tableBuilder.getColumn(context, value, elem);
    if (column == null) {
      // The selected element does not contain a Cell.
      return false;
    }

    resetFocusOnCellImpl(context, value, column, elem);
    return false;
  }

  @Override
  protected void setKeyboardSelected(int index, boolean selected, boolean stealFocus) {
    if (KeyboardSelectionPolicy.DISABLED == getKeyboardSelectionPolicy()
        || !isRowWithinBounds(index)) {
      return;
    }

    // If deselecting, we deselect the previous subrow.
    int subrow = lastKeyboardSelectedSubrow;
    if (selected) {
      subrow = keyboardSelectedSubrow;
      lastKeyboardSelectedSubrow = keyboardSelectedSubrow;
    }

    // Deselect the row.
    TableRowElement tr = getSubRowElement(index + getPageStart(), subrow);
    if (tr == null) {
      // The row does not exist.
      return;
    }
    String cellStyle = style.keyboardSelectedCell();
    boolean updatedSelection = !selected || isFocused || stealFocus;
    setRowStyleName(tr, style.keyboardSelectedRow(), style.keyboardSelectedRowCell(), selected);
    NodeList<TableCellElement> cells = tr.getCells();
    int keyboardColumn = Math.min(getKeyboardSelectedColumn(), cells.getLength() - 1);
    for (int i = 0; i < cells.getLength(); i++) {
      TableCellElement td = cells.getItem(i);
      boolean isKeyboardSelected = (i == keyboardColumn);

      // Update the selected style.
      setStyleName(td, cellStyle, updatedSelection && selected && isKeyboardSelected);

      // Mark as focusable.
      final Element focusable = getKeyboardSelectedElement(td);
      setFocusable(focusable, selected && isKeyboardSelected);

      // Move focus to the cell.
      if (selected && stealFocus && !cellIsEditing && isKeyboardSelected) {
        CellBasedWidgetImpl.get().resetFocus(new Scheduler.ScheduledCommand() {
          @Override
          public void execute() {
            focusable.focus();
          }
        });
      }
    }
  }

  /**
   * Get the column width. Associating a width with a {@link Column} takes
   * precedence over setting the width of a column index.
   * 
   * @param columnIndex the column index
   * @return the column width, or null if none specified
   */
  String getColumnWidth(int columnIndex) {
    String width = null;
    if (columns.size() > columnIndex) {
      // Look for the width by Column.
      width = columnWidths.get(columns.get(columnIndex));
    }
    if (width == null) {
      // Look for the width by index.
      width = columnWidthsByIndex.get(columnIndex);
    }
    return width;
  }

  /**
   * Get a subrow element given the index of the row value and the sub row
   * index.
   * 
   * @param absRow the absolute row value index
   * @param subrow the index of the subrow beneath the row.
   * @return the row element, or null if not found
   */
  // Visible for testing.
  TableRowElement getSubRowElement(int absRow, int subrow) {
    int relRow = absRow - getPageStart();
    checkRowBounds(relRow);

    /*
     * In most tables, the row element that represents the row object at the
     * specified index will be at the same index in the DOM. However, if the
     * user provides a TableBuilder that renders multiple rows per row value,
     * that will not be the case.
     * 
     * We use a binary search to find the row, but we start at the index as that
     * is the most likely location.
     */
    NodeList<TableRowElement> rows = getTableBodyElement().getRows();
    int rowCount = rows.getLength();
    if (rowCount == 0) {
      return null;
    }

    int frameStart = 0;
    int frameEnd = rowCount - 1;
    int domIndex = Math.min(relRow, frameEnd);
    while (domIndex >= frameStart && domIndex <= frameEnd) {
      TableRowElement curRow = rows.getItem(domIndex);
      int rowValueIndex = tableBuilder.getRowValueIndex(curRow);
      if (rowValueIndex == absRow) {
        // Found a subrow in the row index.
        int subrowValueIndex = tableBuilder.getSubrowValueIndex(curRow);
        if (subrow != subrowValueIndex) {
          // Shift to the correct subrow.
          int offset = subrow - subrowValueIndex;
          int subrowIndex = domIndex + offset;
          if (subrowIndex >= rows.getLength()) {
            // The subrow is out of range of the table.
            return null;
          }
          curRow = rows.getItem(subrowIndex);
          if (tableBuilder.getRowValueIndex(curRow) != absRow) {
            // The "subrow" is actually part of the next row.
            return null;
          }
        }
        return curRow;
      } else if (rowValueIndex > absRow) {
        // Shift the frame to lower indexes.
        frameEnd = domIndex - 1;
      } else {
        // Shift the frame to higher indexes.
        frameStart = domIndex + 1;
      }

      // Move the dom index.
      domIndex = (frameStart + frameEnd) / 2;
    }

    // The element wasn't found.
    return null;
  }

  /**
   * Build a list of row values.
   * 
   * @param values the row values to render
   * @param start the absolute start index
   * @param isRebuildingAllRows is this going to rebuild all rows
   * @return a {@link SafeHtml} string containing the row values
   */
  private SafeHtml buildRowValues(List<T> values, int start, boolean isRebuildingAllRows) {
    int length = values.size();
    int end = start + length;
    tableBuilder.start(isRebuildingAllRows);
    for (int i = start; i < end; i++) {
      T value = values.get(i - start);
      tableBuilder.buildRow(value, i);
    }

    // Update the properties of the table.
    coalesceCellProperties();
    TableSectionBuilder tableSectionBuilder = tableBuilder.finish();
    return tableSectionToSafeHtml(tableSectionBuilder, "tbody");
  }

  /**
   * Check that the specified column is within bounds.
   * 
   * @param col the column index
   * @throws IndexOutOfBoundsException if the column is out of bounds
   */
  private void checkColumnBounds(int col) {
    if (col < 0 || col >= getColumnCount()) {
      throw new IndexOutOfBoundsException("Column index is out of bounds: " + col);
    }
  }

  /**
   * Coalesce the various cell properties (dependsOnSelection, handlesSelection,
   * isInteractive) into a table policy.
   */
  private void coalesceCellProperties() {
    dependsOnSelection = false;
    handlesSelection = false;
    isInteractive = false;
    for (HasCell<T, ?> column : tableBuilder.getColumns()) {
      Cell<?> cell = column.getCell();
      if (cell.dependsOnSelection()) {
        dependsOnSelection = true;
      }
      if (cell.handlesSelection()) {
        handlesSelection = true;
      }
      if (isColumnInteractive(column)) {
        isInteractive = true;
      }
    }
  }

  /**
   * Render the header or footer.
   * 
   * @param isFooter true if this is the footer table, false if the header table
   */
  private void createHeaders(boolean isFooter) {
    TableSectionBuilder section =
        isFooter ? footerBuilder.buildFooter() : headerBuilder.buildHeader();
    if (section != null) {
      TABLE_IMPL.replaceAllRows(this, isFooter ? getTableFootElement() : getTableHeadElement(),
          tableSectionToSafeHtml(section, isFooter ? "tfoot" : "thead"));
      doSetHeaderVisible(isFooter, true);
    } else {
      // If the section isn't used, hide it.
      doSetHeaderVisible(isFooter, false);
    }
  }

  /**
   * Fire an event to the Cell within the specified {@link TableCellElement}.
   */
  private <C> void fireEventToCell(Event event, String eventType, Element parentElem,
      final T rowValue, Context context, HasCell<T, C> column) {
    // Check if the cell consumes the event.
    Cell<C> cell = column.getCell();
    if (!cellConsumesEventType(cell, eventType)) {
      return;
    }

    C cellValue = column.getValue(rowValue);
    boolean cellWasEditing = cell.isEditing(context, parentElem, cellValue);
    if (column instanceof Column) {
      /*
       * If the HasCell is a Column, let it handle the event itself. This is
       * here for legacy support.
       */
      Column<T, C> col = (Column<T, C>) column;
      col.onBrowserEvent(context, parentElem, rowValue, event);
    } else {
      // Create a FieldUpdater.
      final FieldUpdater<T, C> fieldUpdater = column.getFieldUpdater();
      final int index = context.getIndex();
      ValueUpdater<C> valueUpdater = (fieldUpdater == null) ? null : new ValueUpdater<C>() {
        @Override
        public void update(C value) {
          fieldUpdater.update(index, rowValue, value);
        }
      };

      // Fire the event to the cell.
      cell.onBrowserEvent(context, parentElem, cellValue, event, valueUpdater);
    }

    // Reset focus if needed.
    cellIsEditing = cell.isEditing(context, parentElem, cellValue);
    if (cellWasEditing && !cellIsEditing) {
      CellBasedWidgetImpl.get().resetFocus(new Scheduler.ScheduledCommand() {
        @Override
        public void execute() {
          setFocus(true);
        }
      });
    }
  }

  /**
   * Get the keyboard selected element from the selected table cell.
   * 
   * @return the keyboard selected element, or null if there is none
   */
  private Element getKeyboardSelectedElement(TableCellElement td) {
    if (td == null) {
      return null;
    }

    /*
     * The TD itself is a cell parent, which means its internal structure
     * (including the tabIndex that we set) could be modified by its Cell. We
     * return the TD to be safe.
     */
    if (tableBuilder.isColumn(td)) {
      return td;
    }

    /*
     * The default table builder adds a focusable div to the table cell because
     * TDs aren't focusable in all browsers. If the user defines a custom table
     * builder with a different structure, we must assume the keyboard selected
     * element is the TD itself.
     */
    Element firstChild = td.getFirstChildElement();
    if (firstChild != null && td.getChildCount() == 1
        && "div".equalsIgnoreCase(firstChild.getTagName())) {
      return firstChild;
    }

    return td;
  }

  /**
   * Get the {@link TableCellElement} that is currently keyboard selected.
   * 
   * @return the table cell element, or null if not selected
   */
  private TableCellElement getKeyboardSelectedTableCellElement() {
    int colIndex = getKeyboardSelectedColumn();
    if (colIndex < 0) {
      return null;
    }

    // Do not use getRowElement() because that will flush the presenter.
    int rowIndex = getKeyboardSelectedRow();
    if (rowIndex < 0 || rowIndex >= getTableBodyElement().getRows().getLength()) {
      return null;
    }
    TableRowElement tr = getSubRowElement(rowIndex + getPageStart(), keyboardSelectedSubrow);
    if (tr != null) {
      int cellCount = tr.getCells().getLength();
      if (cellCount > 0) {
        int column = Math.min(colIndex, cellCount - 1);
        return tr.getCells().getItem(column);
      }
    }
    return null;
  }

  /**
   * Initialize the widget.
   */
  private void init() {
    if (TABLE_IMPL == null) {
      TABLE_IMPL = GWT.create(Impl.class);
    }
    if (template == null) {
      template = GWT.create(Template.class);
    }

    // Sink events.
    Set<String> eventTypes = new HashSet<String>();
    eventTypes.add(BrowserEvents.MOUSEOVER);
    eventTypes.add(BrowserEvents.MOUSEOUT);
    CellBasedWidgetImpl.get().sinkEvents(this, eventTypes);

    // Set the table builder.
    tableBuilder = new DefaultCellTableBuilder<T>(this);
    headerBuilder = new DefaultHeaderOrFooterBuilder<T>(this, false);
    footerBuilder = new DefaultHeaderOrFooterBuilder<T>(this, true);

    // Set the keyboard handler.
    setKeyboardSelectionHandler(new CellTableKeyboardSelectionHandler<T>(this));
  }

  /**
   * Mark the column widths as dirty and redraw the table.
   */
  private void refreshColumnsAndRedraw() {
    columnWidthsDirty = true;
    redraw();
  }

  /**
   * Refresh the headers and column widths.
   */
  private void refreshHeadersAndColumnsImpl() {
    // Refresh the column widths if needed.
    if (columnWidthsDirty) {
      columnWidthsDirty = false;
      refreshColumnWidths();
    }

    // Render the headers and footers.
    boolean wereHeadersDirty = headersDirty;
    headersDirty = false;
    if (wereHeadersDirty || !headerRefreshDisabled) {
      createHeaders(false);
    }
    if (wereHeadersDirty || !footerRefreshDisabled) {
      createHeaders(true);
    }
  }

  private <C> boolean resetFocusOnCellImpl(Context context, T value, HasCell<T, C> column,
      Element cellParent) {
    C cellValue = column.getValue(value);
    Cell<C> cell = column.getCell();
    return cell.resetFocus(context, cellParent, cellValue);
  }

  /**
   * Set a row's hovering style and fire a {@link RowHoverEvent}
   *
   * @param tr the row element
   * @param event the original event
   * @param isHovering false if this is an unhover event
   * @param isRowChange true if the hover event is a full row change, false if it is a hover on a
   *     cell. Row style update is called only on full row change.
   */
  private void setRowHover(TableRowElement tr, Event event, boolean isHovering,
      boolean isRowChange) {
    if (!skipRowHoverStyleUpdate) {
      setRowStyleName(tr, style.hoveredRow(), style.hoveredRowCell(), isHovering);
    }
    RowHoverEvent.fire(this, tr, event, !isHovering,
        isRowChange ? RowHoverEvent.HoveringScope.ROW_HOVER
            : RowHoverEvent.HoveringScope.CELL_HOVER);
  }

  /**
   * Apply a style to a row and all cells in the row.
   * 
   * @param tr the row element
   * @param rowStyle the style to apply to the row
   * @param cellStyle the style to apply to the cells
   * @param add true to add the style, false to remove
   */
  private void setRowStyleName(TableRowElement tr, String rowStyle, String cellStyle, boolean add) {
    setStyleName(tr, rowStyle, add);
    NodeList<TableCellElement> cells = tr.getCells();
    for (int i = 0; i < cells.getLength(); i++) {
      setStyleName(cells.getItem(i), cellStyle, add);
    }
  }

  /**
   * Update the width of all instances of the specified column. A column
   * instance may appear multiple times in the table.
   * 
   * @param column the column to update
   * @param width the width of the column, or null to clear the width
   */
  private void updateColumnWidthImpl(Column<T, ?> column, String width) {
    int columnCount = getColumnCount();
    for (int i = 0; i < columnCount; i++) {
      if (columns.get(i) == column) {
        doSetColumnWidth(i, width);
      }
    }
  }
}
