/*
 * 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.core.client.GWT;
import com.google.gwt.dom.client.BrowserEvents;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.TableLayout;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.TableCellElement;
import com.google.gwt.dom.client.TableColElement;
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.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.CssResource.ImportedWithPrefix;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.resources.client.ImageResource.ImageOptions;
import com.google.gwt.resources.client.ImageResource.RepeatStyle;
import com.google.gwt.user.cellview.client.LoadingStateChangeEvent.LoadingState;
import com.google.gwt.user.client.ui.DeckPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ProvidesKey;

import java.util.HashSet;
import java.util.Set;

/**
 * A tabular view that supports paging and columns.
 * 
 * <p>
 * <h3>Columns</h3> The {@link Column} class defines the
 * {@link com.google.gwt.cell.client.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 com.google.gwt.cell.client.Cell}.
 * </p>
 * 
 * <p>
 * <h3>Headers and Footers</h3> A {@link Header} can be placed at the top
 * (header) or bottom (footer) of the {@link CellTable}. 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>
 * 
 * <p>
 * <h3>Examples</h3>
 * <dl>
 * <dt>Trivial example</dt>
 * <dd>{@example com.google.gwt.examples.cellview.CellTableExample}</dd>
 * <dt>Handling user input with trivial FieldUpdater example</dt>
 * <dd>{@example com.google.gwt.examples.cellview.CellTableFieldUpdaterExample}</dd>
 * <dt>Handling user input with complex FieldUpdater example</dt>
 * <dd>{@example
 * com.google.gwt.examples.cellview.CellTableFieldUpdaterExampleComplex}</dd>
 * <dt>Pushing data with List Data Provider (backed by {@link java.util.List})</dt>
 * <dd>{@example com.google.gwt.examples.view.ListDataProviderExample}</dd>
 * <dt>Pushing data asynchronously with Async Data Provider</dt>
 * <dd>{@example com.google.gwt.examples.view.AsyncDataProviderExample}</dd>
 * <dt>Writing a custom data provider</dt>
 * <dd>{@example com.google.gwt.examples.view.RangeChangeHandlerExample}</dd>
 * <dt>Using a key provider to track objects as they change</dt>
 * <dd>{@example com.google.gwt.examples.view.KeyProviderExample}</dd>
 * </dl>
 * </p>
 * 
 * @param <T> the data type of each row
 */
public class CellTable<T> extends AbstractCellTable<T> implements
    AbstractCellTable.TableSectionChangeHandler {

  /**
   * Resources that match the GWT standard style theme.
   */
  public interface BasicResources extends Resources {
    /**
     * The styles used in this widget.
     */
    @Override
    @Source(BasicStyle.DEFAULT_CSS)
    BasicStyle cellTableStyle();
  }

  /**
   * A ClientBundle that provides images for this widget.
   */
  public interface Resources extends ClientBundle {
    /**
     * The background used for footer cells.
     */
    @Source("cellTableHeaderBackground.png")
    @ImageOptions(repeatStyle = RepeatStyle.Horizontal, flipRtl = true)
    ImageResource cellTableFooterBackground();

    /**
     * The background used for header cells.
     */
    @ImageOptions(repeatStyle = RepeatStyle.Horizontal, flipRtl = true)
    ImageResource cellTableHeaderBackground();

    /**
     * The loading indicator used while the table is waiting for data.
     */
    @ImageOptions(flipRtl = true)
    ImageResource cellTableLoading();

    /**
     * The background used for selected cells.
     */
    @Source("cellListSelectedBackground.png")
    @ImageOptions(repeatStyle = RepeatStyle.Horizontal, flipRtl = true)
    ImageResource cellTableSelectedBackground();

    /**
     * Icon used when a column is sorted in ascending order.
     */
    @Source("sortAscending.png")
    @ImageOptions(flipRtl = true)
    ImageResource cellTableSortAscending();

    /**
     * Icon used when a column is sorted in descending order.
     */
    @Source("sortDescending.png")
    @ImageOptions(flipRtl = true)
    ImageResource cellTableSortDescending();

    /**
     * The styles used in this widget.
     */
    @Source(Style.DEFAULT_CSS)
    Style cellTableStyle();
  }

  /**
   * Styles used by this widget.
   */
  @ImportedWithPrefix("gwt-CellTable")
  public interface Style extends CssResource {
    /**
     * The path to the default CSS styles used by this resource.
     */
    String DEFAULT_CSS = "com/google/gwt/user/cellview/client/CellTable.css";

    /**
     * Applied to every cell.
     */
    String cellTableCell();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    /**
     * Applied to the loading indicator.
     */
    String cellTableLoading();

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

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

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

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

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

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

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

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

  /**
   * Styles used by {@link BasicResources}.
   */
  @ImportedWithPrefix("gwt-CellTable")
  interface BasicStyle extends Style {
    /**
     * The path to the default CSS styles used by this resource.
     */
    String DEFAULT_CSS = "com/google/gwt/user/cellview/client/CellTableBasic.css";
  }

  /**
   * Adapter class to convert {@link Resources} to
   * {@link AbstractCellTable.Resources}.
   */
  private static class ResourcesAdapter implements AbstractCellTable.Resources {

    private final CellTable.Resources resources;
    private final StyleAdapter style;

    public ResourcesAdapter(CellTable.Resources resources) {
      this.resources = resources;
      this.style = new StyleAdapter(resources.cellTableStyle());
    }

    @Override
    public ImageResource sortAscending() {
      return resources.cellTableSortAscending();
    }

    @Override
    public ImageResource sortDescending() {
      return resources.cellTableSortDescending();
    }

    @Override
    public AbstractCellTable.Style style() {
      return style;
    }
  }

  /**
   * Adapter class to convert {@link Style} to {@link AbstractCellTable.Style}.
   */
  private static class StyleAdapter implements AbstractCellTable.Style {
    private final CellTable.Style style;

    public StyleAdapter(CellTable.Style style) {
      this.style = style;
    }

    @Override
    public String cell() {
      return style.cellTableCell();
    }

    @Override
    public String evenRow() {
      return style.cellTableEvenRow();
    }

    @Override
    public String evenRowCell() {
      return style.cellTableEvenRowCell();
    }

    @Override
    public String firstColumn() {
      return style.cellTableFirstColumn();
    }

    @Override
    public String firstColumnFooter() {
      return style.cellTableFirstColumnFooter();
    }

    @Override
    public String firstColumnHeader() {
      return style.cellTableFirstColumnHeader();
    }

    @Override
    public String footer() {
      return style.cellTableFooter();
    }

    @Override
    public String header() {
      return style.cellTableHeader();
    }

    @Override
    public String hoveredRow() {
      return style.cellTableHoveredRow();
    }

    @Override
    public String hoveredRowCell() {
      return style.cellTableHoveredRowCell();
    }

    @Override
    public String keyboardSelectedCell() {
      return style.cellTableKeyboardSelectedCell();
    }

    @Override
    public String keyboardSelectedRow() {
      return style.cellTableKeyboardSelectedRow();
    }

    @Override
    public String keyboardSelectedRowCell() {
      return style.cellTableKeyboardSelectedRowCell();
    }

    @Override
    public String lastColumn() {
      return style.cellTableLastColumn();
    }

    @Override
    public String lastColumnFooter() {
      return style.cellTableLastColumnFooter();
    }

    @Override
    public String lastColumnHeader() {
      return style.cellTableLastColumnHeader();
    }

    @Override
    public String oddRow() {
      return style.cellTableOddRow();
    }

    @Override
    public String oddRowCell() {
      return style.cellTableOddRowCell();
    }

    @Override
    public String selectedRow() {
      return style.cellTableSelectedRow();
    }

    @Override
    public String selectedRowCell() {
      return style.cellTableSelectedRowCell();
    }

    @Override
    public String sortableHeader() {
      return style.cellTableSortableHeader();
    }

    @Override
    public String sortedHeaderAscending() {
      return style.cellTableSortedHeaderAscending();
    }

    @Override
    public String sortedHeaderDescending() {
      return style.cellTableSortedHeaderDescending();
    }

    @Override
    public String widget() {
      return style.cellTableWidget();
    }
  }

  /**
   * The default page size.
   */
  private static final int DEFAULT_PAGESIZE = 15;

  private static Resources DEFAULT_RESOURCES;

  private static Resources getDefaultResources() {
    if (DEFAULT_RESOURCES == null) {
      DEFAULT_RESOURCES = GWT.create(Resources.class);
    }
    return DEFAULT_RESOURCES;
  }

  /**
   * Create the default loading indicator using the loading image in the
   * specified {@link Resources}.
   * 
   * @param resources the resources
   * @return a widget loading indicator
   */
  private static Widget createDefaultLoadingIndicator(Resources resources) {
    ImageResource loadingImg = resources.cellTableLoading();
    return (loadingImg == null) ? null : new Image(loadingImg);
  }

  final TableColElement colgroup;
  private final SimplePanel emptyTableWidgetContainer = new SimplePanel();
  private final SimplePanel loadingIndicatorContainer = new SimplePanel();

  /**
   * A {@link DeckPanel} to hold widgets associated with various loading states.
   */
  private final DeckPanel messagesPanel = new DeckPanel();

  private final Style style;
  private final TableElement table;
  private TableSectionElement tbody;
  private final TableSectionElement tbodyLoading;
  private final TableCellElement tbodyLoadingCell;
  private TableSectionElement tfoot;
  private TableSectionElement thead;
  private boolean colGroupEnabled = true;

  /**
   * Constructs a table with a default page size of 15.
   */
  public CellTable() {
    this(DEFAULT_PAGESIZE);
  }

  /**
   * Constructs a table with the given page size.
   * 
   * @param pageSize the page size
   */
  public CellTable(final int pageSize) {
    this(pageSize, getDefaultResources());
  }

  /**
   * Constructs a table with a default page size of 15, and the given
   * {@link ProvidesKey key provider}.
   * 
   * @param keyProvider an instance of ProvidesKey<T>, or null if the record
   *          object should act as its own key
   */
  public CellTable(ProvidesKey<T> keyProvider) {
    this(DEFAULT_PAGESIZE, keyProvider);
  }

  /**
   * Constructs a table with the given page size with the specified
   * {@link Resources}.
   * 
   * @param pageSize the page size
   * @param resources the resources to use for this widget
   */
  public CellTable(int pageSize, Resources resources) {
    this(pageSize, resources, null);
  }

  /**
   * Constructs a table with the given page size and the given
   * {@link ProvidesKey key provider}.
   * 
   * @param pageSize the page size
   * @param keyProvider an instance of ProvidesKey<T>, or null if the record
   *          object should act as its own key
   */
  public CellTable(int pageSize, ProvidesKey<T> keyProvider) {
    this(pageSize, getDefaultResources(), keyProvider);
  }

  /**
   * Constructs a table with the given page size, the specified
   * {@link Resources}, and the given key provider.
   * 
   * @param pageSize the page size
   * @param resources the resources to use for this widget
   * @param keyProvider an instance of ProvidesKey<T>, or null if the record
   *          object should act as its own key
   */
  public CellTable(final int pageSize, Resources resources, ProvidesKey<T> keyProvider) {
    this(pageSize, resources, keyProvider, createDefaultLoadingIndicator(resources));
  }

  /**
   * Constructs a table with the specified page size, {@link Resources}, key
   * provider, and loading indicator.
   * 
   * @param pageSize the page size
   * @param resources the resources to use for this widget
   * @param keyProvider an instance of ProvidesKey<T>, or null if the record
   *          object should act as its own key
   * @param loadingIndicator the widget to use as a loading indicator, or null
   *          to disable
   */
  public CellTable(final int pageSize, Resources resources, ProvidesKey<T> keyProvider,
      Widget loadingIndicator) {
    this(pageSize, resources, keyProvider, loadingIndicator, true, true);
  }
  
  /**
   * Constructs a table with the specified page size, {@link Resources}, key
   * provider, and loading indicator.
   * 
   * @param pageSize the page size
   * @param resources the resources to use for this widget
   * @param keyProvider an instance of ProvidesKey<T>, or null if the record
   *          object should act as its own key
   * @param loadingIndicator the widget to use as a loading indicator, or null
   *          to disable
   * @param enableColGroup enable colgroup element. This is used when the table is using fixed
   *          layout and when column style is added. Ignoring this element will boost rendering
   *          performance. Note that when colgroup is disabled, {@link #setColumnWidth},
   *          {@link setTableLayoutFixed} and {@link addColumnStyleName} are no longe supported
   * @param attachLoadingPanel attaching the table section that contains the empty table widget and
   *          the loading indicator. Attaching this to the table significantly improve the rendering
   *          performance in webkit based browsers but also introduces significantly larger latency
   *          in IE. If the panel is not attached to the table, it won't be displayed. But the user
   *          can call {@link #getTableLoadingSection} and attach it to other elements outside the
   *          table element
   */
  public CellTable(final int pageSize, Resources resources, ProvidesKey<T> keyProvider,
      Widget loadingIndicator, boolean enableColGroup, boolean attachLoadingPanel) {
    super(Document.get().createTableElement(), pageSize, new ResourcesAdapter(resources),
        keyProvider);
    this.style = resources.cellTableStyle();
    this.style.ensureInjected();
    this.colGroupEnabled = enableColGroup;

    table = getElement().cast();
    table.setCellSpacing(0);
    if (enableColGroup) {
      colgroup = Document.get().createColGroupElement();
      table.appendChild(colgroup);
    } else {
      colgroup = null;
    }
    thead = table.createTHead();
    // Some browsers create a tbody automatically, others do not.
    if (table.getTBodies().getLength() > 0) {
      tbody = table.getTBodies().getItem(0);
    } else {
      tbody = Document.get().createTBodyElement();
      table.appendChild(tbody);
    }
    tbodyLoading = Document.get().createTBodyElement();
    if (attachLoadingPanel) {
      table.appendChild(tbodyLoading);
    }
    tfoot = table.createTFoot();

    // Attach the messages panel.
    {
      tbodyLoadingCell = Document.get().createTDElement();
      TableRowElement tr = Document.get().createTRElement();
      tbodyLoading.appendChild(tr);
      tr.appendChild(tbodyLoadingCell);
      tbodyLoadingCell.setAlign("center");
      tbodyLoadingCell.appendChild(messagesPanel.getElement());
      adopt(messagesPanel);
      messagesPanel.add(emptyTableWidgetContainer);
      messagesPanel.add(loadingIndicatorContainer);
      loadingIndicatorContainer.setStyleName(style.cellTableLoading());
    }

    // Set the loading indicator.
    setLoadingIndicator(loadingIndicator); // Can be null.

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

  @Override
  public void addColumnStyleName(int index, String styleName) {
    assertColumnGroupEnabled("Cannot add column style when colgroup is disabled");
    ensureTableColElement(index).addClassName(styleName);
  }

  /**
   * Return the height of the table body.
   * 
   * @return an int representing the body height
   */
  public int getBodyHeight() {
    return tbody.getClientHeight();
  }

  /**
   * Return the height of the table header.
   * 
   * @return an int representing the header height
   */
  public int getHeaderHeight() {
    return thead.getClientHeight();
  }

  /**
   * Return the section that display loading indicator and the empty table widget. If
   * attachLoadingPanel is set to false in the constructor, this section may not be attached
   * to any element.
   */
  public TableSectionElement getTableLoadingSection() {
    return tbodyLoading;
  }
  
  @Override
  public void onTableBodyChange(TableSectionElement newTBody) {
    tbody = newTBody;
  }

  @Override
  public void onTableFootChange(TableSectionElement newTFoot) {
    tfoot = newTFoot;
  }

  @Override
  public void onTableHeadChange(TableSectionElement newTHead) {
    thead = newTHead;
  }

  @Override
  public void removeColumnStyleName(int index, String styleName) {
    assertColumnGroupEnabled("Cannot remove column style when colgroup is disabled");
    if (index >= colgroup.getChildCount()) {
      return;
    }
    ensureTableColElement(index).removeClassName(styleName);
  }

  /**
   * {@inheritDoc}
   * 
   * <p>
   * The layout behavior depends on whether or not the table is using fixed
   * layout.
   * </p>
   * 
   * @see #setTableLayoutFixed(boolean)
   */
  @Override
  public void setColumnWidth(Column<T, ?> column, String width) {
    assertColumnGroupEnabled("Cannot set column width when colgroup is disabled");
    // Overridden to add JavaDoc comments about fixed layout.
    super.setColumnWidth(column, width);
  }

  /**
   * {@inheritDoc}
   * 
   * <p>
   * The layout behavior depends on whether or not the table is using fixed
   * layout.
   * </p>
   * 
   * @see #setTableLayoutFixed(boolean)
   */
  @Override
  public void setColumnWidth(Column<T, ?> column, double width, Unit unit) {
    // Overridden to add JavaDoc comments about fixed layout.
    super.setColumnWidth(column, width, unit);
  }

  @Override
  public void setEmptyTableWidget(Widget widget) {
    emptyTableWidgetContainer.setWidget(widget);
    super.setEmptyTableWidget(widget);
  }

  @Override
  public void setLoadingIndicator(Widget widget) {
    loadingIndicatorContainer.setWidget(widget);
    super.setLoadingIndicator(widget);
  }

  /**
   * <p>
   * Enable or disable fixed table layout.
   * </p>
   * 
   * <p>
   * <h1>Fixed Table Layout</h1>
   * When using the fixed table layout, cell contents are truncated as needed,
   * which allows you to set the exact width of columns and the table. The
   * default column width is 0 (invisible). In order to see all columns, you
   * must set the width of the table (recommended 100%), or set the width of
   * every column in the table. The following conditions are true for fixed
   * layout tables:
   * <ul>
   * <li>
   * If the widths of <b>all</b> columns are set, the width becomes a weight and
   * the columns are resized proportionally.</li>
   * <li>If the widths of <b>some</b> columns are set using absolute values
   * (PX), those columns are fixed and the remaining width is divided evenly
   * over the other columns. If there is no remaining width, the other columns
   * will not be visible.</li>
   * <li>If the width of some columns are set in absolute values (PX) and others
   * are set in relative values (PCT), the absolute columns will be fixed and
   * the remaining width is divided proportionally over the PCT columns. This
   * allows users to define how the remaining width is allocated.</li>
   * </ul>
   * </p>
   * 
   * @param isFixed true to use fixed table layout, false not to
   * @see <a href="http://www.w3.org/TR/CSS2/tables.html#width-layout">W3C HTML
   *      Specification</a>
   */
  public void setTableLayoutFixed(boolean isFixed) {
    if (isFixed && !colGroupEnabled) {
      throw new IllegalStateException("Cannot set table to fixed layout when colgroup is disabled");
    }
    if (isFixed) {
      table.getStyle().setTableLayout(TableLayout.FIXED);
    } else {
      table.getStyle().clearTableLayout();
    }
  }

  /**
   * Set the width of the width and specify whether or not it should use fixed
   * table layout. See {@link #setTableLayoutFixed(boolean)} for more
   * information about fixed layout tables.
   * 
   * @param width the width of the table
   * @param isFixedLayout true to use fixed width layout, false not to
   * @see #setTableLayoutFixed(boolean)
   * @see <a href="http://www.w3.org/TR/CSS2/tables.html#width-layout">W3C HTML
   *      Specification</a>
   */
  public final void setWidth(String width, boolean isFixedLayout) {
    super.setWidth(width);
    setTableLayoutFixed(isFixedLayout);
  }

  @Override
  protected void doSetColumnWidth(int column, String width) {
    // This is invoked when column width is set (which will throw an exception if colgroup is not
    // enabled), and refreshColumnWidth/clearColumnWidth. The latter two are no op if setColumnWidth
    // is not invoked first.
    if (colGroupEnabled) {
      if (width == null) {
        ensureTableColElement(column).getStyle().clearWidth();
      } else {
        ensureTableColElement(column).getStyle().setProperty("width", width);
      }
    }
  }

  @Override
  protected void doSetHeaderVisible(boolean isFooter, boolean isVisible) {
    setVisible(isFooter ? tfoot : thead, isVisible);
  }

  @Override
  protected TableSectionElement getTableBodyElement() {
    return tbody;
  }

  @Override
  protected TableSectionElement getTableFootElement() {
    return tfoot;
  }

  @Override
  protected TableSectionElement getTableHeadElement() {
    return thead;
  }

  /**
   * Called when the loading state changes.
   * 
   * @param state the new loading state
   */
  @Override
  protected void onLoadingStateChanged(LoadingState state) {
    Widget message = null;
    if (state == LoadingState.LOADING) {
      // Loading indicator.
      message = loadingIndicatorContainer;
    } else if (state == LoadingState.LOADED && getPresenter().isEmpty()) {
      // Empty table.
      message = emptyTableWidgetContainer;
    }

    // Switch out the message to display.
    if (message != null) {
      messagesPanel.showWidget(messagesPanel.getWidgetIndex(message));
    }

    // Adjust the colspan of the messages panel container.
    tbodyLoadingCell.setColSpan(Math.max(1, getRealColumnCount()));

    // Show the correct container.
    showOrHide(getChildContainer(), message == null);
    showOrHide(tbodyLoading, message != null);

    // Fire an event.
    super.onLoadingStateChanged(state);
  }

  @Override
  protected void refreshColumnWidths() {
    super.refreshColumnWidths();

    /*
     * Set the width to zero and the display to none for all col elements that 
     * appear after the last column. Clearing the width would cause it to take 
     * up the remaining width in a fixed layout table.
     * 
     * Clear the display for all columns that appear in the table. 
     */
    if (colGroupEnabled) {
      int colCount = colgroup.getChildCount();
      int lastColumn = getRealColumnCount(); 
      for (int i = 0; i < lastColumn; i++) {
        ensureTableColElement(i).getStyle().clearDisplay();
      }
      for (int i = lastColumn; i < colCount; i++) {
        doSetColumnWidth(i, "0px");
        ensureTableColElement(i).getStyle().setDisplay(Display.NONE);
      }
    }
  }

  @Override
  protected void doAttachChildren() {
    super.doAttachChildren();
    doAttach(messagesPanel);
  }

  @Override
  protected void doDetachChildren() {
    super.doDetachChildren();
    doDetach(messagesPanel);
  }

  /**
   * Assert if colgroup is enabled, and throw an exception with the supplied message if it's not
   * enabled.
   */
  private void assertColumnGroupEnabled(String message) {
    if (!colGroupEnabled) {
      throw new IllegalStateException(message);
    }
  }
  
  /**
   * Get the {@link TableColElement} at the specified index, creating it if
   * necessary.
   * 
   * @param index the column index
   * @return the {@link TableColElement}
   */
  private TableColElement ensureTableColElement(int index) {
    // Ensure that we have enough columns.
    for (int i = colgroup.getChildCount(); i <= index; i++) {
      colgroup.appendChild(Document.get().createColElement());
    }
    return colgroup.getChild(index).cast();
  }
}
