/*******************************************************************************
 * Copyright (c) 2002, 2019 Innoopract Informationssysteme GmbH and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Innoopract Informationssysteme GmbH - initial API and implementation
 *    EclipseSource - ongoing development
 ******************************************************************************/
package org.eclipse.swt.widgets;

import static org.eclipse.rap.rwt.internal.textsize.TextSizeUtil.stringExtent;
import static org.eclipse.swt.internal.widgets.MarkupUtil.checkWidgetState;
import static org.eclipse.swt.internal.widgets.MarkupUtil.isMarkupEnabledFor;
import static org.eclipse.swt.internal.widgets.MarkupUtil.isToolTipMarkupEnabledFor;
import static org.eclipse.swt.internal.widgets.MarkupValidator.isValidationDisabledFor;

import org.eclipse.rap.rwt.RWT;
import org.eclipse.rap.rwt.internal.lifecycle.ProcessActionRunner;
import org.eclipse.rap.rwt.internal.lifecycle.WidgetLCA;
import org.eclipse.rap.rwt.internal.textsize.TextSizeUtil;
import org.eclipse.rap.rwt.internal.theme.CssBoxDimensions;
import org.eclipse.rap.rwt.internal.theme.Size;
import org.eclipse.rap.rwt.internal.theme.ThemeAdapter;
import org.eclipse.rap.rwt.template.Template;
import org.eclipse.rap.rwt.theme.BoxDimensions;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.internal.SerializableCompatibility;
import org.eclipse.swt.internal.widgets.ICellToolTipAdapter;
import org.eclipse.swt.internal.widgets.ICellToolTipProvider;
import org.eclipse.swt.internal.widgets.IControlAdapter;
import org.eclipse.swt.internal.widgets.IItemHolderAdapter;
import org.eclipse.swt.internal.widgets.ITableAdapter;
import org.eclipse.swt.internal.widgets.ItemHolder;
import org.eclipse.swt.internal.widgets.MarkupValidator;
import org.eclipse.swt.internal.widgets.tablekit.TableLCA;
import org.eclipse.swt.internal.widgets.tablekit.TableThemeAdapter;


/**
 * Instances of this class implement a selectable user interface
 * object that displays a list of images and strings and issues
 * notification when selected.
 * <p>
 * The item children that may be added to instances of this class
 * must be of type <code>TableItem</code>.
 * </p><p>
 * Style <code>VIRTUAL</code> is used to create a <code>Table</code> whose
 * <code>TableItem</code>s are to be populated by the client on an on-demand basis
 * instead of up-front.  This can provide significant performance improvements for
 * tables that are very large or for which <code>TableItem</code> population is
 * expensive (for example, retrieving values from an external source).
 * </p><p>
 * Here is an example of using a <code>Table</code> with style <code>VIRTUAL</code>:
 * <code><pre>
 *  final Table table = new Table (parent, SWT.VIRTUAL | SWT.BORDER);
 *  table.setItemCount (1000000);
 *  table.addListener (SWT.SetData, new Listener () {
 *      public void handleEvent (Event event) {
 *          TableItem item = (TableItem) event.item;
 *          int index = table.indexOf (item);
 *          item.setText ("Item " + index);
 *          System.out.println (item.getText ());
 *      }
 *  });
 * </pre></code>
 * </p><p>
 * Note that although this class is a subclass of <code>Composite</code>,
 * it does not make sense to add <code>Control</code> children to it,
 * or set a layout on it.
 * </p><p>
 * <dl>
 * <dt><b>Styles:</b></dt>
 * <dd>SINGLE, MULTI, CHECK, FULL_SELECTION, HIDE_SELECTION, VIRTUAL</dd>
 * <dt><b>Events:</b></dt>
 * <dd>Selection, DefaultSelection, SetData<!--, MeasureItem, EraseItem, PaintItem--></dd>
 * </dl>
 * </p><p>
 * Note: Only one of the styles SINGLE, and MULTI may be specified.
 * </p><p>
 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
 * </p>
 *
 * @since 1.0
 */
public class Table extends Composite {

  // handle the fact that we have two item types to deal with
  private final class CompositeItemHolder implements IItemHolderAdapter<Item> {
    @Override
    public void add( Item item ) {
      if( item instanceof TableColumn ) {
        columnHolder.add( ( TableColumn )item );
      } else {
        String msg = "Only TableColumns may be added to CompositeItemHolder";
        throw new IllegalArgumentException( msg );
      }
    }
    @Override
    public void insert( Item item, int index ) {
      if( item instanceof TableColumn ) {
        columnHolder.insert( ( TableColumn )item, index );
      } else {
        String msg = "Only TableColumns may be inserted to CompositeItemHolder";
        throw new IllegalArgumentException( msg );
      }
    }
    @Override
    public void remove( Item item ) {
      if( item instanceof TableColumn ) {
        columnHolder.remove( ( TableColumn )item );
      } else {
        String msg = "Only TableColumns may be removed from CompositeItemHolder";
        throw new IllegalArgumentException( msg );
      }
    }
    @Override
    public Item[] getItems() {
      TableItem[] items = getCreatedItems();
      Item[] columns = columnHolder.getItems();
      Item[] result = new Item[ columns.length + items.length ];
      System.arraycopy( columns, 0, result, 0, columns.length );
      System.arraycopy( items, 0, result, columns.length, items.length );
      return result;
    }
  }

  private final class TableAdapter
    implements ITableAdapter, ICellToolTipAdapter, SerializableCompatibility
  {
    private String toolTipText;
    private ICellToolTipProvider provider;

    @Override
    public int getCheckWidthWithMargin() {
      return Table.this.getCheckSize().x;
    }

    @Override
    public int getCheckLeft() {
      return getCheckBoxMargin().left;
    }

    @Override
    public int getCheckWidth() {
      return getThemeAdapter().getCheckBoxImageSize( Table.this ).width;
    }

    @Override
    public int getItemImageWidth( int columnIndex ) {
      int result = 0;
      if( hasColumnImages( columnIndex ) ) {
        result = getItemImageSize().x;
      }
      return result;
    }

    @Override
    public int getFocusIndex() {
      return focusIndex;
    }

    @Override
    public void setFocusIndex( int focusIndex ) {
      Table.this.setFocusIndex( focusIndex );
    }

    @Override
    public int getColumnLeftOffset( int columnIndex ) {
      return Table.this.getColumnLeftOffset( columnIndex );
    }

    @Override
    public int getColumnLeft( TableColumn column ) {
      int index = Table.this.indexOf( column );
      return columnHolder.getItem( index ).getLeft();
    }

    @Override
    public int getLeftOffset() {
      return leftOffset;
    }

    @Override
    public void setLeftOffset( int leftOffset ) {
      Table.this.leftOffset = leftOffset;
    }

    @Override
    public void checkData() {
      Table.this.checkData();
    }

    @Override
    public void checkData( final int index ) {
      if( ( Table.this.style & SWT.VIRTUAL ) != 0  ) {
        ProcessActionRunner.add( new Runnable() {
          @Override
          public void run() {
            if( index >= 0 && index < itemCount ) {
              TableItem item = _getItem( index );
              if( !item.isDisposed() ) {
                Table.this.checkData( item, index );
              }
            }
          }
        } );
      }
    }

    @Override
    public int getDefaultColumnWidth() {
      int result = 0;
      TableItem[] items = Table.this.getCachedItems();
      for( int i = 0; i < items.length; i++ ) {
        result = Math.max( result, items[ i ].getPackWidth( 0 ) );
      }
      return result;
    }

    @Override
    public boolean isItemVirtual( int index ) {
      boolean result = false;
      if( ( style & SWT.VIRTUAL ) != 0 ) {
        TableItem item = items[ index ];
        result = item == null || !item.cached;
      }
      return result;
    }

    @Override
    public TableItem[] getCachedItems() {
      return Table.this.getCachedItems();
    }

    @Override
    public TableItem[] getCreatedItems() {
      return Table.this.getCreatedItems();
    }

    @Override
    public TableItem getMeasureItem() {
      return Table.this.getMeasureItem();
    }

    @Override
    public ICellToolTipProvider getCellToolTipProvider() {
      return provider;
    }

    @Override
    public void setCellToolTipProvider( ICellToolTipProvider provider ) {
      this.provider = provider;
    }

    @Override
    public String getCellToolTipText() {
      return toolTipText;
    }

    @Override
    public void setCellToolTipText( String toolTipText ) {
      if(    toolTipText != null
          && isToolTipMarkupEnabledFor( Table.this )
          && !isValidationDisabledFor( Table.this ) )
      {
        MarkupValidator.getInstance().validate( toolTipText );
      }
      this.toolTipText = toolTipText;
    }

    @Override
    public int getFixedColumns() {
      return Table.this.getFixedColumns();
    }

    @Override
    public boolean isFixedColumn( TableColumn column ) {
      return Table.this.isFixedColumn( Table.this.indexOf( column ) );
    }
  }

  /**
   * <strong>IMPORTANT:</strong> This field is <em>not</em> part of the SWT
   * public API. It is marked public only so that it can be shared
   * within the packages provided by SWT. It should never be accessed from
   * application code.
   */
  public static final String ALWAYS_HIDE_SELECTION = Table.class.getName() + "#alwaysHideSelection";

  private static final int GRID_WIDTH = 1;
  private static final int[] EMPTY_SELECTION = new int[ 0 ];

  private transient CompositeItemHolder itemHolder;
  private final ITableAdapter tableAdapter;
  private int customItemHeight;
  private int itemCount;
  private TableItem[] items;
  private final ItemHolder<TableColumn> columnHolder;
  private int[] columnImageCount;
  private int[] columnOrder;
  private int[] selection;
  private boolean linesVisible;
  private boolean headerVisible;
  private Color headerBackground;
  private Color headerForeground;
  private boolean hasVScrollBar;
  private boolean hasHScrollBar;
  private int topIndex;
  int leftOffset;
  private int focusIndex;
  private TableColumn sortColumn;
  private int sortDirection;
  private Point itemImageSize;
  private BoxDimensions bufferedCellPadding;
  private int bufferedCellSpacing;
  private int preloadedItems;

  /**
   * Constructs a new instance of this class given its parent
   * and a style value describing its behavior and appearance.
   * <p>
   * The style value is either one of the style constants defined in
   * class <code>SWT</code> which is applicable to instances of this
   * class, or must be built by <em>bitwise OR</em>'ing together
   * (that is, using the <code>int</code> "|" operator) two or more
   * of those <code>SWT</code> style constants. The class description
   * lists the style constants that are applicable to the class.
   * Style bits are also inherited from superclasses.
   * </p>
   *
   * @param parent a composite control which will be the parent of the new instance (cannot be null)
   * @param style the style of control to construct
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
   *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
   * </ul>
   *
   * @see SWT#SINGLE
   * @see SWT#MULTI
   * @see SWT#CHECK
   * @see SWT#FULL_SELECTION
   * @see SWT#HIDE_SELECTION
   * @see SWT#VIRTUAL
   * @see Widget#checkSubclass
   * @see Widget#getStyle
   */
  public Table( Composite parent, int style ) {
    super( parent, checkStyle( style ) );
    focusIndex = -1;
    sortDirection = SWT.NONE;
    tableAdapter = new TableAdapter();
    columnHolder = new ItemHolder<>( TableColumn.class );
    setTableEmpty();
    selection = EMPTY_SELECTION;
    customItemHeight = -1;
    bufferedCellSpacing = -1;
  }

  @Override
  void initState() {
    removeState( /* CANVAS | */ THEME_BACKGROUND );
  }

  @Override
  @SuppressWarnings("unchecked")
  public <T> T getAdapter( Class<T> adapter ) {
    if( adapter == IItemHolderAdapter.class ) {
      if( itemHolder == null ) {
        itemHolder = new CompositeItemHolder();
      }
      return ( T )itemHolder;
    }
    if( adapter == ITableAdapter.class || adapter == ICellToolTipAdapter.class ) {
      return ( T )tableAdapter;
    }
    if( adapter == WidgetLCA.class ) {
      return ( T )TableLCA.INSTANCE;
    }
    return super.getAdapter( adapter );
  }

  @Override
  public void setData( String key, Object value ) {
    if( RWT.CUSTOM_ITEM_HEIGHT.equals( key ) ) {
      setCustomItemHeight( value );
    } else if( RWT.PRELOADED_ITEMS.equals( key ) ) {
      setPreloadedItems( value );
    }
    if( !RWT.MARKUP_ENABLED.equals( key ) || !isMarkupEnabledFor( this ) ) {
      checkWidgetState( key, () -> itemCount == 0 );
      super.setData( key, value );
    }
  }

  ///////////////////////////
  // Column handling methods

  /**
   * Returns the number of columns contained in the receiver.
   * If no <code>TableColumn</code>s were created by the programmer,
   * this value is zero, despite the fact that visually, one column
   * of items may be visible. This occurs when the programmer uses
   * the table like a list, adding items but never creating a column.
   *
   * @return the number of columns
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public int getColumnCount() {
    checkWidget();
    return columnHolder.size();
  }

  /**
   * Returns an array of <code>TableColumn</code>s which are the
   * columns in the receiver.  Columns are returned in the order
   * that they were created.  If no <code>TableColumn</code>s were
   * created by the programmer, the array is empty, despite the fact
   * that visually, one column of items may be visible. This occurs
   * when the programmer uses the table like a list, adding items but
   * never creating a column.
   * <p>
   * Note: This is not the actual structure used by the receiver
   * to maintain its list of items, so modifying the array will
   * not affect the receiver.
   * </p>
   *
   * @return the items in the receiver
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @see Table#getColumnOrder()
   * @see Table#setColumnOrder(int[])
   * @see TableColumn#getMoveable()
   * @see TableColumn#setMoveable(boolean)
   * @see SWT#Move
   */
  public TableColumn[] getColumns() {
    checkWidget();
    return columnHolder.getItems();
  }

  /**
   * Returns the column at the given, zero-relative index in the
   * receiver. Throws an exception if the index is out of range.
   * Columns are returned in the order that they were created.
   * If no <code>TableColumn</code>s were created by the programmer,
   * this method will throw <code>ERROR_INVALID_RANGE</code> despite
   * the fact that a single column of data may be visible in the table.
   * This occurs when the programmer uses the table like a list, adding
   * items but never creating a column.
   *
   * @param index the index of the column to return
   * @return the column at the given index
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @see Table#getColumnOrder()
   * @see Table#setColumnOrder(int[])
   * @see TableColumn#getMoveable()
   * @see TableColumn#setMoveable(boolean)
   * @see SWT#Move
   */
  public TableColumn getColumn( int index ) {
    checkWidget();
    return columnHolder.getItem( index );
  }

  /**
   * Searches the receiver's list starting at the first column
   * (index 0) until a column is found that is equal to the
   * argument, and returns the index of that column. If no column
   * is found, returns -1.
   *
   * @param tableColumn the search column
   * @return the index of the column
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public int indexOf( TableColumn tableColumn ) {
    checkWidget();
    if( tableColumn == null ) {
      SWT.error( SWT.ERROR_NULL_ARGUMENT );
    }
    return columnHolder.indexOf( tableColumn );
  }

  /**
   * Sets the order that the items in the receiver should
   * be displayed in to the given argument which is described
   * in terms of the zero-relative ordering of when the items
   * were added.
   *
   * @param order the new order to display the items
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_NULL_ARGUMENT - if the item order is null</li>
   *    <li>ERROR_INVALID_ARGUMENT - if the item order is not the same length as the number of items</li>
   * </ul>
   *
   * @see Table#getColumnOrder()
   * @see TableColumn#getMoveable()
   * @see TableColumn#setMoveable(boolean)
   * @see SWT#Move
   */
  public void setColumnOrder( int[] order ) {
    checkWidget();
    if( order == null ) {
      SWT.error( SWT.ERROR_NULL_ARGUMENT );
    }
    int columnCount = columnHolder.size();
    if( order.length != columnCount ) {
      SWT.error( SWT.ERROR_INVALID_ARGUMENT );
    }
    if( columnCount > 0 ) {
      int[] oldOrder = new int[ columnCount ];
      System.arraycopy( columnOrder, 0, oldOrder, 0, columnOrder.length );
      boolean reorder = false;
      boolean[] seen = new boolean[ columnCount ];
      for( int i = 0; i < order.length; i++ ) {
        int index = order[ i ];
        if( index < 0 || index >= columnCount ) {
          SWT.error( SWT.ERROR_INVALID_RANGE );
        }
        if( seen[ index ] ) {
          SWT.error( SWT.ERROR_INVALID_ARGUMENT );
        }
        seen[ index ] = true;
        if( index != oldOrder[ i ] ) {
          reorder = true;
        }
      }
      if( reorder ) {
        System.arraycopy( order, 0, columnOrder, 0, columnOrder.length );
        for( int i = 0; i < seen.length; i++ ) {
          if( oldOrder[ i ] != columnOrder[ i ] ) {
            TableColumn column = columnHolder.getItem( columnOrder[ i ] );
            column.notifyListeners( SWT.Move, new Event() );
          }
        }
      }
    }
  }

  /**
   * Returns an array of zero-relative integers that map
   * the creation order of the receiver's items to the
   * order in which they are currently being displayed.
   * <p>
   * Specifically, the indices of the returned array represent
   * the current visual order of the items, and the contents
   * of the array represent the creation order of the items.
   * </p><p>
   * Note: This is not the actual structure used by the receiver
   * to maintain its list of items, so modifying the array will
   * not affect the receiver.
   * </p>
   *
   * @return the current visual order of the receiver's items
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @see Table#setColumnOrder(int[])
   * @see TableColumn#getMoveable()
   * @see TableColumn#setMoveable(boolean)
   * @see SWT#Move
   */
  public int[] getColumnOrder() {
    checkWidget();
    int[] result;
    if( columnHolder.size() == 0 ) {
      result = new int[ 0 ];
    } else {
      result = new int[ columnOrder.length ];
      System.arraycopy( columnOrder, 0, result, 0, columnOrder.length );
    }
    return result;
  }

  ////////////////////////
  // Item handling methods

  /**
   * Sets the number of items contained in the receiver.
   *
   * @param count the number of items
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public void setItemCount( int count ) {
    checkWidget();
    int oldItemCount = itemCount;
    int newItemCount = Math.max( 0, count );
    if( newItemCount != oldItemCount && !isInDispose() ) {
      int deleteIndex = oldItemCount - 1;
      while( deleteIndex >= newItemCount ) {
        TableItem item = items[ deleteIndex ];
        if( item != null && !item.isDisposed() ) {
          item.dispose();
        } else {
          destroyItem( null, deleteIndex );
        }
        deleteIndex--;
      }
      int length = Math.max( 4, ( newItemCount + 3 ) / 4 * 4 );
      TableItem[] newItems = new TableItem[ length ];
      System.arraycopy( items, 0, newItems, 0, Math.min( newItemCount, itemCount ) );
      items = newItems;
      if( ( style & SWT.VIRTUAL ) == 0 ) {
        for( int i = itemCount; i < newItemCount; i++ ) {
          items[ i ] = new TableItem( this, SWT.NONE, i, true );
        }
      }
      itemCount = newItemCount;
      adjustTopIndex();
      if( focusIndex > itemCount - 1 ) {
        adjustFocusIndex();
      }
      if( ( style & SWT.VIRTUAL ) != 0 ) {
        updateScrollBars();
      }
      redraw();
    }
  }

  /**
   * Returns the number of items contained in the receiver.
   *
   * @return the number of items
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public int getItemCount() {
    checkWidget();
    return itemCount;
  }

  /**
   * Returns a (possibly empty) array of <code>TableItem</code>s which
   * are the items in the receiver.
   * <p>
   * Note: This is not the actual structure used by the receiver
   * to maintain its list of items, so modifying the array will
   * not affect the receiver.
   * </p>
   *
   * @return the items in the receiver
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public TableItem[] getItems() {
    checkWidget();
    TableItem[] result = new TableItem[ itemCount ];
    if( ( style & SWT.VIRTUAL ) != 0 ) {
      for( int i = 0; i < itemCount; i++ ) {
        result[ i ] = _getItem( i );
      }
    } else {
      System.arraycopy( items, 0, result, 0, itemCount );
    }
    return result;
  }

  /**
   * Returns the item at the given, zero-relative index in the
   * receiver. Throws an exception if the index is out of range.
   *
   * @param index the index of the item to return
   * @return the item at the given index
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public TableItem getItem( int index ) {
    checkWidget();
    if( index < 0 || index >= itemCount ) {
      SWT.error( SWT.ERROR_INVALID_RANGE );
    }
    return _getItem( index );
  }

  /**
   * Returns the item at the given point in the receiver
   * or null if no such item exists. The point is in the
   * coordinate system of the receiver.
   * <p>
   * The item that is returned represents an item that could be selected by the user.
   * For example, if selection only occurs in items in the first column, then null is
   * returned if the point is outside of the item.
   * Note that the SWT.FULL_SELECTION style hint, which specifies the selection policy,
   * determines the extent of the selection.
   * </p>
   *
   * @param point the point used to locate the item
   * @return the item at the given point, or null if the point is not in a selectable item
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public TableItem getItem( Point point ) {
    checkWidget();
    if( point == null ) {
      SWT.error( SWT.ERROR_NULL_ARGUMENT );
    }
    TableItem result = null;
    int headerHeight = getHeaderHeight();
    Rectangle itemArea = getClientArea();
    itemArea.y += headerHeight;
    if( itemArea.contains( point ) ) {
      int itemHeight = getItemHeight();
      int index = ( ( point.y - headerHeight ) / itemHeight ) - 1;
      if( point.y == headerHeight || point.y % itemHeight != 0 ) {
        index++;
      }
      index += topIndex;
      if( index >= 0 && index < itemCount ) {
        result = _getItem( index );
      }
    }
    return result;
  }

  /**
   * Searches the receiver's list starting at the first item
   * (index 0) until an item is found that is equal to the
   * argument, and returns the index of that item. If no item
   * is found, returns -1.
   *
   * @param item the search item
   * @return the index of the item
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public int indexOf( TableItem item ) {
    checkWidget();
    if( item == null ) {
      SWT.error( SWT.ERROR_NULL_ARGUMENT );
    }
    return item.parent == this ? item.index : -1;
  }

  /**
   * Removes all of the items from the receiver.
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public void removeAll() {
    checkWidget();
    while( itemCount > 0 ) {
      removeItem( itemCount - 1 );
    }
  }

  /**
   * Removes the items from the receiver which are between the given
   * zero-relative start and end indices (inclusive).
   *
   * @param start the start of the range
   * @param end the end of the range
   * @exception IllegalArgumentException
   *              <ul>
   *              <li>ERROR_INVALID_RANGE - if either the start or end are not
   *              between 0 and the number of elements in the list minus 1
   *              (inclusive)</li>
   *              </ul>
   * @exception SWTException
   *              <ul>
   *              <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *              <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
   *              thread that created the receiver</li>
   *              </ul>
   */
  public void remove( int start, int end ) {
    checkWidget();
    if( start <= end ) {
      if( !( 0 <= start && start <= end && end < itemCount ) ) {
        error( SWT.ERROR_INVALID_RANGE );
      }
      for( int i = end; i >= start; i-- ) {
        removeItem( i );
      }
    }
  }

  /**
   * Removes the item from the receiver at the given zero-relative index.
   *
   * @param index the index for the item
   * @exception IllegalArgumentException
   *              <ul>
   *              <li>ERROR_INVALID_RANGE - if the index is not between 0 and
   *              the number of elements in the list minus 1 (inclusive)</li>
   *              </ul>
   * @exception SWTException
   *              <ul>
   *              <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *              <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
   *              thread that created the receiver</li>
   *              </ul>
   */
  public void remove( int index ) {
    checkWidget();
    if( !( 0 <= index && index < itemCount ) ) {
      SWT.error( SWT.ERROR_ITEM_NOT_REMOVED );
    }
    removeItem( index );
  }

  /**
   * Removes the items from the receiver's list at the given zero-relative
   * indices.
   *
   * @param indices the array of indices of the items
   * @exception IllegalArgumentException
   *              <ul>
   *              <li>ERROR_INVALID_RANGE - if the index is not between 0 and
   *              the number of elements in the list minus 1 (inclusive)</li>
   *              <li>ERROR_NULL_ARGUMENT - if the indices array is null</li>
   *              </ul>
   * @exception SWTException
   *              <ul>
   *              <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *              <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
   *              thread that created the receiver</li>
   *              </ul>
   */
  public void remove( int[] indices ) {
    checkWidget();
    if( indices == null ) {
      error( SWT.ERROR_NULL_ARGUMENT );
    }
    if( indices.length > 0 ) {
      int[] sortedIndices = new int[ indices.length ];
      System.arraycopy( indices, 0, sortedIndices, 0, indices.length );
      sort( sortedIndices );
      int start = sortedIndices[ sortedIndices.length - 1 ];
      int end = sortedIndices[ 0 ];
      if( !( 0 <= start && start <= end && end < itemCount ) ) {
        SWT.error( SWT.ERROR_INVALID_RANGE );
      }
      int lastValue = -1;
      for( int i = 0; i < sortedIndices.length; i++ ) {
        if( sortedIndices[ i ] != lastValue ) {
          lastValue = sortedIndices[ i ];
          removeItem( sortedIndices[ i ] );
        }
      }
      if( itemCount == 0 ) {
        setTableEmpty();
      }
    }
  }

  /**
   * Clears the item at the given zero-relative index in the receiver.
   * The text, icon and other attributes of the item are set to the default
   * value.  If the table was created with the <code>SWT.VIRTUAL</code> style,
   * these attributes are requested again as needed.
   *
   * @param index the index of the item to clear
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @see SWT#VIRTUAL
   * @see SWT#SetData
   */
  public void clear( int index ) {
    checkWidget();
    if( index < 0 || index >= itemCount ) {
      SWT.error( SWT.ERROR_INVALID_RANGE );
    }
    TableItem item = items[ index ];
    if( item != null ) {
      item.clear();
    }
  }

  /**
   * Removes the items from the receiver which are between the given
   * zero-relative start and end indices (inclusive).  The text, icon
   * and other attributes of the items are set to their default values.
   * If the table was created with the <code>SWT.VIRTUAL</code> style,
   * these attributes are requested again as needed.
   *
   * @param start the start index of the item to clear
   * @param end the end index of the item to clear
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @see SWT#VIRTUAL
   * @see SWT#SetData
   */
  public void clear( int start, int end ) {
    checkWidget();
    if( start <= end ) {
      if( !( 0 <= start && start <= end && end < itemCount ) ) {
        SWT.error( SWT.ERROR_INVALID_RANGE );
      }
      if( start == 0 && end == itemCount - 1 ) {
        clearAll();
      } else {
        for( int i = start; i <= end; i++ ) {
          TableItem item = items[ i ];
          if( item != null ) {
            item.clear();
          }
        }
      }
    }
  }

  /**
   * Clears all the items in the receiver. The text, icon and other
   * attributes of the items are set to their default values. If the
   * table was created with the <code>SWT.VIRTUAL</code> style, these
   * attributes are requested again as needed.
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @see SWT#VIRTUAL
   * @see SWT#SetData
   */
  public void clearAll() {
    checkWidget();
    for( int i = 0; i < itemCount; i++ ) {
      TableItem item = items[ i ];
      if( item != null ) {
        item.clear();
      }
    }
    clearItemImageSize();
  }

  /**
   * Clears the items at the given zero-relative indices in the receiver.
   * The text, icon and other attributes of the items are set to their default
   * values.  If the table was created with the <code>SWT.VIRTUAL</code> style,
   * these attributes are requested again as needed.
   *
   * @param indices the array of indices of the items
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
   *    <li>ERROR_NULL_ARGUMENT - if the indices array is null</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @see SWT#VIRTUAL
   * @see SWT#SetData
   */
  public void clear( int[] indices ) {
    checkWidget();
    if( indices == null ) {
      SWT.error( SWT.ERROR_NULL_ARGUMENT );
    }
    if( indices.length > 0 ) {
      for( int i = 0; i < indices.length; i++ ) {
        if( !( 0 <= indices[ i ] && indices[ i ] < itemCount ) ) {
          SWT.error( SWT.ERROR_INVALID_RANGE );
        }
      }
      for( int i = 0; i < indices.length; i++ ) {
        TableItem item = items[ indices[ i ] ];
        if( item != null ) {
          item.clear();
        }
      }
    }
  }

  /////////////////////////////
  // Selection handling methods

  /**
   * Returns the zero-relative index of the item which is currently
   * selected in the receiver, or -1 if no item is selected.
   *
   * @return the index of the selected item
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public int getSelectionIndex() {
    checkWidget();
    int result = -1;
    int topSelectedIndex = -1;
    for( int i = 0; i < selection.length; i++ ) {
      if( focusIndex == selection[ i ] ) {
        result = selection[ i ];
      }
      if( topSelectedIndex == -1 ) {
        topSelectedIndex = selection[ i ];
      } else {
        topSelectedIndex = Math.min( topSelectedIndex, selection[ i ] );
      }
    }
    if( result == -1 ) {
      result = topSelectedIndex;
    }
    return result;
  }

  /**
   * Selects the item at the given zero-relative index in the receiver.
   * The current selection is first cleared, then the new item is selected.
   *
   * @param index the index of the item to select
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @see Table#deselectAll()
   * @see Table#select(int)
   */
  public void setSelection( int index ) {
    checkWidget();
    deselectAll();
    select( index );
    setFocusIndex( index );
    showSelection();
  }

  /**
   * Returns the number of selected items contained in the receiver.
   *
   * @return the number of selected items
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public int getSelectionCount() {
    checkWidget();
    return selection.length;
  }

  /**
   * Selects the items in the range specified by the given zero-relative
   * indices in the receiver. The range of indices is inclusive.
   * The current selection is cleared before the new items are selected.
   * <p>
   * Indices that are out of range are ignored and no items will be selected
   * if start is greater than end.
   * If the receiver is single-select and there is more than one item in the
   * given range, then all indices are ignored.
   * </p>
   *
   * @param start the start index of the items to select
   * @param end the end index of the items to select
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @see Table#deselectAll()
   * @see Table#select(int,int)
   */
  public void setSelection( int start, int end ) {
    checkWidget();
    deselectAll();
    select( start, end );
    if( end >= 0 && start <= end && ( ( style & SWT.SINGLE ) == 0 || start == end ) ) {
      setFocusIndex( Math.max( 0, start ) );
    }
    showSelection();
  }

  /**
   * Returns an array of <code>TableItem</code>s that are currently
   * selected in the receiver. The order of the items is unspecified.
   * An empty array indicates that no items are selected.
   * <p>
   * Note: This is not the actual structure used by the receiver
   * to maintain its selection, so modifying the array will
   * not affect the receiver.
   * </p>
   * @return an array representing the selection
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public TableItem[] getSelection() {
    checkWidget();
    int length = selection.length;
    TableItem[] result = new TableItem[ length ];
    for( int i = 0; i < selection.length; i++ ) {
      result[ i ] = _getItem( selection[ i ] );
    }
    return result;
  }

  /**
   * Selects the items at the given zero-relative indices in the receiver.
   * The current selection is cleared before the new items are selected.
   * <p>
   * Indices that are out of range and duplicate indices are ignored.
   * If the receiver is single-select and multiple indices are specified,
   * then all indices are ignored.
   * </p>
   *
   * @param indices the indices of the items to select
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_NULL_ARGUMENT - if the array of indices is null</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @see Table#deselectAll()
   * @see Table#select(int[])
   */
  public void setSelection( int[] indices ) {
    checkWidget();
    if( indices == null ) {
      SWT.error( SWT.ERROR_NULL_ARGUMENT );
    }
    deselectAll();
    select( indices );
    int length = indices.length;
    if( length != 0 && ( ( style & SWT.SINGLE ) == 0 || length <= 1 ) ) {
      setFocusIndex( indices[ 0 ] );
    }
    showSelection();
  }

  /**
   * Sets the receiver's selection to the given item.
   * The current selection is cleared before the new item is selected.
   * <p>
   * If the item is not in the receiver, then it is ignored.
   * </p>
   *
   * @param item the item to select
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_NULL_ARGUMENT - if the item is null</li>
   *    <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public void setSelection( TableItem item ) {
    checkWidget();
    if( item == null ) {
      error( SWT.ERROR_NULL_ARGUMENT );
    }
    setSelection( new TableItem[]{ item } );
  }

  /**
   * Sets the receiver's selection to be the given array of items.
   * The current selection is cleared before the new items are selected.
   * <p>
   * Items that are not in the receiver are ignored.
   * If the receiver is single-select and multiple items are specified,
   * then all items are ignored.
   * </p>
   *
   * @param items the array of items
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_NULL_ARGUMENT - if the array of items is null</li>
   *    <li>ERROR_INVALID_ARGUMENT - if one of the items has been disposed</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @see Table#deselectAll()
   * @see Table#select(int[])
   * @see Table#setSelection(int[])
   */
  public void setSelection( TableItem[] items ) {
    checkWidget();
    if( items == null ) {
      SWT.error( SWT.ERROR_NULL_ARGUMENT );
    }
    int[] indices = new int[ items.length ];
    for( int i = 0; i < items.length; i++ ) {
      indices[ i ] = indexOf( items[ i ] );
    }
    setSelection( indices );
  }

  /**
   * Returns the zero-relative indices of the items which are currently
   * selected in the receiver. The order of the indices is unspecified.
   * The array is empty if no items are selected.
   * <p>
   * Note: This is not the actual structure used by the receiver
   * to maintain its selection, so modifying the array will
   * not affect the receiver.
   * </p>
   * @return the array of indices of the selected items
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public int[] getSelectionIndices() {
    checkWidget();
    // TODO [rh] directly return a copy of the selection array
    TableItem[] currentSelection = getSelection();
    int[] result = new int[ currentSelection.length ];
    for( int i = 0; i < currentSelection.length; i++ ) {
      result[ i ] = indexOf( currentSelection[ i ] );
    }
    return result;
  }

  /**
   * Returns <code>true</code> if the item is selected,
   * and <code>false</code> otherwise.  Indices out of
   * range are ignored.
   *
   * @param index the index of the item
   * @return the visibility state of the item at the index
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public boolean isSelected( int index ) {
    checkWidget();
    boolean result = false;
    if( index >= 0 && index < itemCount ) {
      for( int i = 0; !result && i < selection.length; i++ ) {
        result = selection[ i ] == index;
      }
    }
    return result;
  }

  /**
   * Selects the item at the given zero-relative index in the receiver.
   * If the item at the index was already selected, it remains
   * selected. Indices that are out of range are ignored.
   *
   * @param index the index of the item to select
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public void select( int index ) {
    checkWidget();
    if( index >= 0 && index < itemCount ) {
      if( ( style & SWT.SINGLE ) != 0 ) {
        selection = new int[] { index };
      } else {
        if( !isSelected( index ) ) {
          int length = selection.length;
          int[] newSelection = new int[ length + 1 ];
          System.arraycopy( selection, 0, newSelection, 0, length );
          newSelection[ length ] = index;
          selection = newSelection;
        }
      }
    }
  }

  /**
   * Selects the items in the range specified by the given zero-relative
   * indices in the receiver. The range of indices is inclusive.
   * The current selection is not cleared before the new items are selected.
   * <p>
   * If an item in the given range is not selected, it is selected.
   * If an item in the given range was already selected, it remains selected.
   * Indices that are out of range are ignored and no items will be selected
   * if start is greater than end.
   * If the receiver is single-select and there is more than one item in the
   * given range, then all indices are ignored.
   * </p>
   *
   * @param start the start of the range
   * @param end the end of the range
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @see Table#setSelection(int,int)
   */
  public void select( int start, int end ) {
    checkWidget();
    if( end >= 0 && start <= end && ( ( style & SWT.SINGLE ) == 0 || start == end ) ) {
      if( itemCount != 0 && start < itemCount ) {
        int adjustedStart = Math.max( 0, start );
        int adjustedEnd = Math.min( end, itemCount - 1 );
        if( adjustedStart == 0 && adjustedEnd == itemCount - 1 ) {
          selectAll();
        } else {
          for( int i = adjustedStart; i <= adjustedEnd; i++ ) {
            select( i );
          }
        }
      }
    }
  }

  /**
   * Selects the items at the given zero-relative indices in the receiver.
   * The current selection is not cleared before the new items are selected.
   * <p>
   * If the item at a given index is not selected, it is selected.
   * If the item at a given index was already selected, it remains selected.
   * Indices that are out of range and duplicate indices are ignored.
   * If the receiver is single-select and multiple indices are specified,
   * then all indices are ignored.
   * </p>
   *
   * @param indices the array of indices for the items to select
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_NULL_ARGUMENT - if the array of indices is null</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @see Table#setSelection(int[])
   */
  public void select( int[] indices ) {
    checkWidget();
    if( indices == null ) {
      error( SWT.ERROR_NULL_ARGUMENT );
    }
    int length = indices.length;
    if( length != 0 && ( ( style & SWT.SINGLE ) == 0 || length <= 1 ) ) {
      for( int i = length - 1; i >= 0; --i ) {
        select( indices[ i ] );
      }
    }
  }

  /**
   * Selects all of the items in the receiver.
   * <p>
   * If the receiver is single-select, do nothing.
   * </p>
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  // TODO [rh] revise: a VIRTUAL table would resolve all its items when
  //      selectAll is called. Compare how SWT handles this.
  public void selectAll() {
    checkWidget();
    if( ( style & SWT.SINGLE ) == 0 ) {
      setSelection( getItems() );
    }
  }

  /**
   * Deselects the item at the given zero-relative index in the receiver.
   * If the item at the index was already deselected, it remains
   * deselected. Indices that are out of range are ignored.
   *
   * @param index the index of the item to deselect
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public void deselect( int index ) {
    checkWidget();
    removeFromSelection( index );
  }

  /**
   * Deselects the items at the given zero-relative indices in the receiver.
   * If the item at the given zero-relative index in the receiver
   * is selected, it is deselected.  If the item at the index
   * was not selected, it remains deselected.  The range of the
   * indices is inclusive. Indices that are out of range are ignored.
   *
   * @param start the start index of the items to deselect
   * @param end the end index of the items to deselect
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public void deselect( int start, int end ) {
    checkWidget();
    if( start == 0 && end == itemCount - 1 ) {
      deselectAll();
    } else {
      int actualStart = Math.max( 0, start );
      for( int i = actualStart; i <= end; i++ ) {
        removeFromSelection( i );
      }
    }
  }

  /**
   * Deselects the items at the given zero-relative indices in the receiver.
   * If the item at the given zero-relative index in the receiver
   * is selected, it is deselected.  If the item at the index
   * was not selected, it remains deselected. Indices that are out
   * of range and duplicate indices are ignored.
   *
   * @param indices the array of indices for the items to deselect
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_NULL_ARGUMENT - if the set of indices is null</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public void deselect( int[] indices ) {
    checkWidget();
    if( indices == null ) {
      error( SWT.ERROR_NULL_ARGUMENT );
    }
    for( int i = 0; i < indices.length; i++ ) {
      removeFromSelection( indices[ i ] );
    }
  }

  /**
   * Deselects all selected items in the receiver.
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public void deselectAll() {
    checkWidget();
    selection = EMPTY_SELECTION;
  }

  //////////////////////////////////
  // TopIndex and showItem/Selection

  /**
   * Sets the zero-relative index of the item which is currently
   * at the top of the receiver. This index can change when items
   * are scrolled or new items are added and removed.
   *
   * @param topIndex the index of the top item
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public void setTopIndex( int topIndex ) {
    checkWidget();
    if( this.topIndex != topIndex && topIndex >= 0 && topIndex < itemCount ) {
      this.topIndex = topIndex;
      adjustTopIndex();
      if( ( style & SWT.VIRTUAL ) != 0 ) {
        redraw();
      }
    }
  }

  /**
   * Returns the zero-relative index of the item which is currently
   * at the top of the receiver. This index can change when items are
   * scrolled or new items are added or removed.
   *
   * @return the index of the top item
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public int getTopIndex() {
    checkWidget();
    return topIndex;
  }

  /**
   * Shows the item.  If the item is already showing in the receiver,
   * this method simply returns.  Otherwise, the items are scrolled until
   * the item is visible.
   *
   * @param item the item to be shown
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_NULL_ARGUMENT - if the item is null</li>
   *    <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @see Table#showSelection()
   */
  public void showItem( TableItem item ) {
    checkWidget();
    if( item == null ) {
      error( SWT.ERROR_NULL_ARGUMENT );
    }
    if( item.isDisposed() ) {
      error( SWT.ERROR_INVALID_ARGUMENT );
    }
    int itemIndex = indexOf( item );
    int itemCount = getVisibleItemCount( false );
    if( itemIndex < topIndex ) {
      // Show item as top item
      setTopIndex( itemIndex );
    } else if( itemCount > 0 && itemIndex >= topIndex + itemCount ) {
      // Show item as last item
      setTopIndex( itemIndex - itemCount + 1 );
    }
  }

  /**
   * Shows the column.  If the column is already showing in the receiver,
   * this method simply returns.  Otherwise, the columns are scrolled until
   * the column is visible.
   *
   * @param column the column to be shown
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_NULL_ARGUMENT - if the column is null</li>
   *    <li>ERROR_INVALID_ARGUMENT - if the column has been disposed</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @since 1.3
   */
  public void showColumn( TableColumn column ) {
    checkWidget();
    if( column == null ) {
      error( SWT.ERROR_NULL_ARGUMENT );
    }
    if( column.isDisposed() ) {
      error( SWT.ERROR_INVALID_ARGUMENT );
    }
    if( column.getParent() == this ) {
      int index = indexOf( column );
      if( 0 <= index && index < getColumnCount() ) {
        int leftColumnsWidth = 0;
        int columnWidth = column.getWidth();
        int clientWidth = getClientArea().width;
        int[] columnOrder = getColumnOrder();
        boolean found = false;
        for( int i = 0; i < columnOrder.length; i++ ) {
          if( index != columnOrder[ i ] ) {
            int currentColumnWidth = getColumn( columnOrder[ i ] ).getWidth();
            if( !found ) {
              if( isFixedColumn( columnOrder[ i ] ) ) {
                clientWidth -= currentColumnWidth;
              } else {
                leftColumnsWidth += currentColumnWidth;
              }
            }
          } else {
            found = true;
          }
        }
        if( getColumnLeftOffset( index ) > leftColumnsWidth ) {
          leftOffset = leftColumnsWidth;
        } else if( leftOffset < leftColumnsWidth + columnWidth - clientWidth ) {
          leftOffset = leftColumnsWidth + columnWidth - clientWidth;
        }
      }
    }
  }

  /**
   * Shows the selection.  If the selection is already showing in the receiver,
   * this method simply returns.  Otherwise, the items are scrolled until
   * the selection is visible.
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @see Table#showItem(TableItem)
   */
  public void showSelection() {
    checkWidget();
    int index = getSelectionIndex();
    if( index != -1 ) {
      showItem( _getItem( index ) );
    }
  }

  ////////////////////
  // Visual appearance

  /**
   * Marks the receiver's header as visible if the argument is <code>true</code>,
   * and marks it invisible otherwise.
   * <p>
   * If one of the receiver's ancestors is not visible or some
   * other condition makes the receiver not visible, marking
   * it visible may not actually cause it to be displayed.
   * </p>
   *
   * @param headerVisible the new visibility state
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public void setHeaderVisible( boolean headerVisible ) {
    checkWidget();
    boolean changed = headerVisible != this.headerVisible;
    this.headerVisible = headerVisible;
    if( changed ) {
      updateScrollBars();
    }
  }

  /**
   * Returns <code>true</code> if the receiver's header is visible,
   * and <code>false</code> otherwise.
   * <p>
   * If one of the receiver's ancestors is not visible or some
   * other condition makes the receiver not visible, this method
   * may still indicate that it is considered visible even though
   * it may not actually be showing.
   * </p>
   *
   * @return the receiver's header's visibility state
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public boolean getHeaderVisible() {
    checkWidget();
    return headerVisible;
  }

  /**
   * Sets the header background color to the color specified
   * by the argument, or to the default system color if the argument is null.
   * @param color the new color (or null)
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   * @since 3.6
   */
  public void setHeaderBackground( Color color ) {
    checkWidget();
    if( color != null && color.isDisposed() ) {
      error( SWT.ERROR_INVALID_ARGUMENT );
    }
    headerBackground = color;
  }

  /**
   * Returns the header background color.
   *
   * @return the receiver's header background color.
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   * @since 3.6
   */
  public Color getHeaderBackground() {
    checkWidget();
    return headerBackground;
  }

  /**
   * Sets the header foreground color to the color specified
   * by the argument, or to the default system color if the argument is null.
   * @param color the new color (or null)
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   * @since 3.6
   */
  public void setHeaderForeground( Color color ) {
    checkWidget();
    if( color != null && color.isDisposed() ) {
      error( SWT.ERROR_INVALID_ARGUMENT );
    }
    headerForeground = color;
  }

  /**
   * Returns the header foreground color.
   *
   * @return the receiver's header foreground color.
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   * @since 3.6
   */
  public Color getHeaderForeground() {
    checkWidget();
    return headerForeground;
  }

  /**
   * Returns <code>true</code> if the receiver's lines are visible,
   * and <code>false</code> otherwise.
   * <p>
   * If one of the receiver's ancestors is not visible or some
   * other condition makes the receiver not visible, this method
   * may still indicate that it is considered visible even though
   * it may not actually be showing.
   * </p>
   *
   * @return the visibility state of the lines
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public boolean getLinesVisible() {
    checkWidget();
    return linesVisible;
  }

  /**
   * Marks the receiver's lines as visible if the argument is <code>true</code>,
   * and marks it invisible otherwise.
   * <p>
   * If one of the receiver's ancestors is not visible or some
   * other condition makes the receiver not visible, marking
   * it visible may not actually cause it to be displayed.
   * </p>
   *
   * @param linesVisible the new visibility state
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public void setLinesVisible( boolean linesVisible ) {
    checkWidget();
    this.linesVisible = linesVisible;
  }

  /**
   * Sets the column used by the sort indicator for the receiver. A null
   * value will clear the sort indicator.  The current sort column is cleared
   * before the new column is set.
   *
   * @param column the column used by the sort indicator or <code>null</code>
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_INVALID_ARGUMENT - if the column is disposed</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public void setSortColumn( TableColumn column ) {
    checkWidget();
    if( column != null && column.isDisposed() ) {
      error( SWT.ERROR_INVALID_ARGUMENT );
    }
    sortColumn = column;
  }

  /**
   * Returns the column which shows the sort indicator for
   * the receiver. The value may be null if no column shows
   * the sort indicator.
   *
   * @return the sort indicator
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @see #setSortColumn(TableColumn)
   */
  public TableColumn getSortColumn() {
    checkWidget();
    return sortColumn;
  }

  /**
   * Sets the direction of the sort indicator for the receiver. The value
   * can be one of <code>UP</code>, <code>DOWN</code> or <code>NONE</code>.
   *
   * @param direction the direction of the sort indicator
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public void setSortDirection( int direction ) {
    checkWidget();
    if( ( direction & ( SWT.UP | SWT.DOWN ) ) != 0 || direction == SWT.NONE ) {
      sortDirection = direction;
    }
  }

  /**
   * Returns the direction of the sort indicator for the receiver.
   * The value will be one of <code>UP</code>, <code>DOWN</code>
   * or <code>NONE</code>.
   *
   * @return the sort direction
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @see #setSortDirection(int)
   */
  public int getSortDirection() {
    checkWidget();
    return sortDirection;
  }

  ///////////////////////////////////
  // Dimensions and size calculations

  /**
   * Returns the height of the area which would be used to
   * display <em>one</em> of the items in the receiver's.
   *
   * @return the height of one item
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public int getItemHeight() {
    checkWidget();
    int result = customItemHeight;
    if( result == -1 ) {
      int textHeight = TextSizeUtil.getCharHeight( getFont() );
      int imageHeight = getItemImageSize().y;
      BoxDimensions cellPadding = getCellPadding();
      result = Math.max( imageHeight, textHeight ) + cellPadding.top + cellPadding.bottom;
      if( ( style & SWT.CHECK ) != 0 ) {
        result = Math.max( getCheckSize().y, result );
      }
    }
    return result;
  }

  /**
   * Returns the height of the receiver's header
   *
   * @return the height of the header or zero if the header is not visible
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public int getHeaderHeight() {
    checkWidget();
    int result = 0;
    if( headerVisible ) {
      Font headerFont = getHeaderFont();
      int textHeight = TextSizeUtil.getCharHeight( headerFont );
      int imageHeight = 0;
      for( int i = 0; i < columnHolder.size(); i++ ) {
        TableColumn column = columnHolder.getItem( i );
        if( column.getText().contains( "\n" ) ) {
          int columnTextHeight = TextSizeUtil.textExtent( headerFont, column.getText(), 0 ).y;
          textHeight = Math.max( textHeight, columnTextHeight );
        }
        Image image = column.getImage();
        int height = image == null ? 0 : image.getBounds().height;
        if( height > imageHeight ) {
          imageHeight = height;
        }
      }
      result = Math.max( textHeight, imageHeight );
      TableThemeAdapter themeAdapter = getThemeAdapter();
      BoxDimensions headerPadding = themeAdapter.getHeaderPadding( this );
      result += themeAdapter.getHeaderBorderBottomWidth( this );
      result += headerPadding.top + headerPadding.bottom;
    }
    return result;
  }

  /**
   * Returns the width in pixels of a grid line.
   *
   * @return the width of a grid line in pixels
   *
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   */
  public int getGridLineWidth () {
    checkWidget();
    return GRID_WIDTH;
  }

  //////////////////
  // Selection event

  /**
   * Adds the listener to the collection of listeners who will
   * be notified when the receiver's selection changes, by sending
   * it one of the messages defined in the <code>SelectionListener</code>
   * interface.
   * <p>
   * When <code>widgetSelected</code> is called, the item field of the event object is valid.
   * If the receiver has <code>SWT.CHECK</code> style set and the check selection changes,
   * the event object detail field contains the value <code>SWT.CHECK</code>.
   * <code>widgetDefaultSelected</code> is typically called when an item is double-clicked.
   * The item field of the event object is valid for default selection, but the detail field is not used.
   * </p>
   *
   * @param listener the listener which should be notified
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @see SelectionListener
   * @see #removeSelectionListener
   * @see SelectionEvent
   */
  public void addSelectionListener( SelectionListener listener ) {
    checkWidget();
    if( listener == null ) {
      SWT.error( SWT.ERROR_NULL_ARGUMENT );
    }
    TypedListener typedListener = new TypedListener( listener );
    addListener( SWT.Selection, typedListener );
    addListener( SWT.DefaultSelection, typedListener );
  }

  /**
   * Removes the listener from the collection of listeners who will
   * be notified when the receiver's selection changes.
   *
   * @param listener the listener which should no longer be notified
   *
   * @exception IllegalArgumentException <ul>
   *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
   * </ul>
   * @exception SWTException <ul>
   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
   * </ul>
   *
   * @see SelectionListener
   * @see #addSelectionListener(SelectionListener)
   */
  public void removeSelectionListener( SelectionListener listener ) {
    checkWidget();
    if( listener == null ) {
      SWT.error( SWT.ERROR_NULL_ARGUMENT );
    }
    removeListener( SWT.Selection, listener );
    removeListener( SWT.DefaultSelection, listener );
  }

  @Override
  public void setFont( Font font ) {
    super.setFont( font );
    clearItemsTextWidths();
    updateScrollBars();
  }

  ////////////////////
  // Widget dimensions

  @Override
  public Point computeSize( int wHint, int hHint, boolean changed ) {
    checkWidget();
    int width = 0;
    int height = 0;
    if( columnHolder.size() > 0 ) {
      for( int i = 0; i < columnHolder.size(); i++ ) {
        width += columnHolder.getItem( i ).getWidth();
      }
    } else {
      width = getItemsPreferredWidth( 0 );
    }
    height += getHeaderHeight();
    height += getItemCount() * getItemHeight();
    if( width == 0 ) {
      width = DEFAULT_WIDTH;
    }
    if( height == 0 ) {
      height = DEFAULT_HEIGHT;
    }
    if( wHint != SWT.DEFAULT ) {
      width = wHint;
    }
    if( hHint != SWT.DEFAULT ) {
      height = hHint;
    }
    BoxDimensions border = getBorder();
    width += border.left + border.right;
    height += border.top + border.bottom;
    if( ( style & SWT.V_SCROLL ) != 0 ) {
      width += getVerticalBar().getSize().x;
    }
    if( ( style & SWT.H_SCROLL ) != 0 ) {
      height += getHorizontalBar().getSize().y;
    }
    return new Point( width, height );
  }

  private void setCustomItemHeight( Object value ) {
    if( value == null ) {
      customItemHeight = -1;
    } else {
      if( !( value instanceof Integer ) ) {
        error( SWT.ERROR_INVALID_ARGUMENT );
      }
      int itemHeight = ( ( Integer )value ).intValue();
      if( itemHeight < 0 ) {
        error( SWT.ERROR_INVALID_RANGE );
      }
      customItemHeight = itemHeight;
    }
  }

  private void setPreloadedItems( Object value ) {
    if( value == null ) {
      preloadedItems = 0;
    } else {
      if( !( value instanceof Integer ) ) {
        error( SWT.ERROR_INVALID_ARGUMENT );
      }
      preloadedItems = ( ( Integer )value ).intValue();
      if( preloadedItems < 0 ) {
        error( SWT.ERROR_INVALID_RANGE );
      }
    }
  }

  final int getItemsPreferredWidth( int columnIndex ) {
    // Mimic Windows behaviour that has a minimal width
    int width = getCheckSize( columnIndex ).x + 12;
    // dont't access virtual items, they would get resolved unintentionally
    TableItem[] items = getCachedItems();
    for( int i = 0; i < items.length; i++ ) {
      int checkWidth = items[ i ].getCheckWidth( columnIndex );
      int packWidth = items[ i ].getPackWidth( columnIndex );
      int itemWidth = checkWidth + packWidth;
      if( itemWidth > width ) {
        width = itemWidth;
      }
    }
    return width;
  }

  private void clearItemsTextWidths() {
    TableItem[] items = getCreatedItems();
    for( int i = 0; i < items.length; i++ ) {
      items[ i ].clearTextWidths();
    }
  }

  @Override
  public void changed( Control[] changed ) {
    clearItemsTextWidths();
    super.changed( changed );
  }

  /////////////////////////////
  // Create and destroy columns

  final void createColumn( TableColumn column, int index ) {
    columnHolder.insert( column, index );
    if( columnOrder == null ) {
      columnOrder = new int[] { index };
    } else {
      int length = columnOrder.length;
      for( int i = index; i < length; i++ ) {
        columnOrder[ i ]++;
      }
      int[] newColumnOrder = new int[ length + 1 ];
      System.arraycopy( columnOrder, 0, newColumnOrder, 0, index );
      System.arraycopy( columnOrder, index, newColumnOrder, index + 1, length - index );
      columnOrder = newColumnOrder;
      columnOrder[ index ] = index;
    }
    if( columnImageCount == null ) {
      columnImageCount = new int[] { 0 };
    } else if( columnHolder.size() > 1 ) {
      int length = columnImageCount.length;
      int[] newColumnImageCount = new int[ length + 1 ];
      System.arraycopy( columnImageCount, 0, newColumnImageCount, 0, index );
      System.arraycopy( columnImageCount, index, newColumnImageCount, index + 1, length - index );
      columnImageCount = newColumnImageCount;
    }
    for( int i = 0; i < itemCount; i++ ) {
      if( items[ i ] != null ) {
        items[ i ].shiftData( index );
      }
    }
    updateScrollBars();
  }

  final void destroyColumn( TableColumn column ) {
    if( !isInDispose() ) {
      int index = indexOf( column );
      // Remove data from TableItems
      for( int i = 0; i < itemCount; i++ ) {
        if( items[ i ] != null ) {
          items[ i ].removeData( index );
        }
      }
      // Reset sort column if necessary
      if( column == sortColumn ) {
        sortColumn = null;
      }
      // Remove from column holder
      columnHolder.remove( column );
      // Remove from column order
      int length = columnOrder.length;
      int[] newColumnOrder = new int[ length - 1 ];
      int count = 0;
      for( int i = 0; i < length; i++ ) {
        if( columnOrder[ i ] != index ) {
          int newOrder = columnOrder[ i ];
          if( index < newOrder ) {
            newOrder--;
          }
          newColumnOrder[ count ] = newOrder;
          count++;
        }
      }
      columnOrder = newColumnOrder;
      // Remove from columnImageCount
      if( columnImageCount.length == 1 ) {
        columnImageCount = null;
      } else {
        count = 0;
        int[] newColumnImageCount = new int[ columnImageCount.length - 1 ];
        for( int i = 0; i < columnImageCount.length; i++ ) {
          if( i != index ) {
            newColumnImageCount[ count ] = columnImageCount[ i ];
            count++;
          }
        }
        columnImageCount = newColumnImageCount;
      }
      updateScrollBars();
    }
  }

  ////////////////////////////
  // Create and destroy items

  final void createItem( TableItem item, int index ) {
    if( index < 0 || index > itemCount ) {
      error( SWT.ERROR_INVALID_RANGE );
    }
    if( itemCount == items.length ) {
      /*
       * Grow the array faster when redraw is off or the table is not visible.
       * When the table is painted, the items array is resized to be smaller to
       * reduce memory usage.
       */
      boolean small = /* drawCount == 0 && */isVisible();
      int length = small ? items.length + 4 : Math.max( 4, items.length * 3 / 2 );
      TableItem[] newItems = new TableItem[ length ];
      System.arraycopy( items, 0, newItems, 0, items.length );
      items = newItems;
    }
    /* Insert the item */
    System.arraycopy( items, index, items, index + 1, itemCount - index );
    items[ index ] = item;
    itemCount++;
    adjustItemIndices( index );
    // adjust the selection indices
    for( int i = 0; i < selection.length; i++ ) {
      if( selection[ i ] >= index ) {
        selection[ i ] = selection[ i ] + 1;
      }
    }
    // advance focusIndex when an item is inserted before the focused item
    if( index <= focusIndex ) {
      focusIndex++;
    }
    updateScrollBars();
  }

  final void destroyItem( TableItem item, int index ) {
    if( !isInDispose() ) {
      removeFromSelection( index );
      adjustSelectionIdices( index );
      if( item != null ) {
        int columnCount = Math.max( 1, columnHolder.size() );
        for( int i = 0; i < columnCount; i++ ) {
          updateColumnImageCount( i, item.getImageInternal( i ), null );
        }
      }
      itemCount--;
      if( item != null ) {
        item.index = -1;
      }
      if( itemCount == 0 ) {
        setTableEmpty();
      } else {
        System.arraycopy( items, index + 1, items, index, itemCount - index );
        items[ itemCount ] = null;
        adjustItemIndices( index );
      }
      adjustTopIndex();
      if( index == focusIndex || focusIndex > itemCount - 1 ) {
        adjustFocusIndex();
      }
      updateScrollBars();
      if( ( style & SWT.VIRTUAL ) != 0 ) {
        redraw();
      }
    }
  }

  ////////////////
  // Destroy table

  @Override
  void releaseChildren() {
    Item[] tableItems = new TableItem[ items.length ];
    System.arraycopy( items, 0, tableItems, 0, items.length );
    for( int i = 0; i < tableItems.length; i++ ) {
      if( tableItems[ i ] != null ) {
        tableItems[ i ].dispose();
        items[ i ] = null;
      }
    }
    TableColumn[] tableColumns = columnHolder.getItems();
    for( int i = 0; i < tableColumns.length; i++ ) {
      tableColumns[ i ].dispose();
      columnHolder.remove( tableColumns[ i ] );
    }
    super.releaseChildren();
  }

  ///////////////////////////////////
  // Helping methods - item retrieval

  private TableItem _getItem( int index ) {
    if( ( style & SWT.VIRTUAL ) != 0 && items[ index ] == null ) {
      items[ index ] = new TableItem( this, SWT.NONE, index, false );
    }
    return items[ index ];
  }

  final TableItem[] getCachedItems() {
    TableItem[] result;
    if( ( style & SWT.VIRTUAL ) != 0 ) {
      int count = 0;
      for( int i = 0; i < itemCount; i++ ) {
        if( items[ i ] != null && items[ i ].cached ) {
          count++;
        }
      }
      result = new TableItem[ count ];
      count = 0;
      for( int i = 0; i < itemCount; i++ ) {
        if( items[ i ] != null && items[ i ].cached ) {
          result[ count ] = items[ i ];
          count++;
        }
      }
    } else {
      result = new TableItem[ itemCount ];
      System.arraycopy( items, 0, result, 0, itemCount );
    }
    return result;
  }

  final TableItem[] getCreatedItems() {
    TableItem[] result;
    if( ( style & SWT.VIRTUAL ) != 0 ) {
      int count = 0;
      for( int i = 0; i < itemCount; i++ ) {
        if( items[ i ] != null ) {
          count++;
        }
      }
      result = new TableItem[ count ];
      count = 0;
      for( int i = 0; i < itemCount; i++ ) {
        if( items[ i ] != null ) {
          result[ count ] = items[ i ];
          count++;
        }
      }
    } else {
      result = new TableItem[ itemCount ];
      System.arraycopy( items, 0, result, 0, itemCount );
    }
    return result;
  }

  ///////////////////////////////////////////////
  // Helping methods - resolving of virtual items

  private void checkData() {
    int visibleItemCount = getVisibleItemCount( true );
    int startIndex = Math.max( 0, topIndex - preloadedItems );
    int endIndex = Math.min( itemCount, topIndex + visibleItemCount + preloadedItems );
    for( int index = startIndex; index < endIndex; index++ ) {
      checkData( _getItem( index ), index );
    }
  }

  final boolean checkData( TableItem item, int index ) {
    boolean result = true;
    boolean virtual = ( style & SWT.VIRTUAL ) != 0;
    if( virtual && !item.cached && index >= 0 && index < itemCount ) {
      item.cached = true;
      Event event = new Event();
      event.item = item;
      event.index = index;
      notifyListeners( SWT.SetData, event );
      // widget could be disposed at this point
      if( isDisposed() || item.isDisposed() ) {
        result = false;
      }
    }
    return result;
  }

  ////////////////////////////////////
  // Helping methods - item image size

  final void updateColumnImageCount( int columnIndex, Image oldImage, Image newImage ) {
    int delta = 0;
    if( oldImage == null && newImage != null ) {
      delta = +1;
    } else if( oldImage != null && newImage == null ) {
      delta = -1;
    }
    if( delta != 0 ) {
      if( columnImageCount == null ) {
        int columnCount = Math.max( 1, columnHolder.size() );
        columnImageCount = new int[ columnCount ];
      }
      columnImageCount[ columnIndex ] += delta;
    }
  }

  final boolean hasColumnImages( int columnIndex ) {
    return columnImageCount == null ? false : columnImageCount[ columnIndex ] > 0;
  }

  final void updateItemImageSize( Image image ) {
    if( image != null && itemImageSize == null ) {
      Rectangle imageBounds = image.getBounds();
      itemImageSize = new Point( imageBounds.width, imageBounds.height );
    }
  }

  final Point getItemImageSize() {
    return itemImageSize == null ? new Point( 0, 0 ) : itemImageSize;
  }

  final void clearItemImageSize() {
    itemImageSize = null;
  }

  BoxDimensions getCellPadding() {
    if( bufferedCellPadding == null ) {
      bufferedCellPadding = getThemeAdapter().getCellPadding( this );
    }
    return bufferedCellPadding;
  }

  int getCellSpacing() {
    if( bufferedCellSpacing < 0 ) {
      bufferedCellSpacing = getThemeAdapter().getCellSpacing( _getParent() );
    }
    return bufferedCellSpacing;
  }

  ///////////////////////////////////////
  // Helping methods - dynamic scrollbars

  boolean hasVScrollBar() {
    return hasVScrollBar;
  }

  boolean hasHScrollBar() {
    return hasHScrollBar;
  }

  @Override
  int getVScrollBarWidth() {
    int result = 0;
    if( hasVScrollBar() ) {
      result = getVerticalBar().getSize().x;
    }
    return result;
  }

  @Override
  int getHScrollBarHeight() {
    int result = 0;
    if( hasHScrollBar() ) {
      result = getHorizontalBar().getSize().y;
    }
    return result;
  }

  void updateScrollBars() {
    if( ( style & SWT.NO_SCROLL ) == 0 ) {
      hasVScrollBar = false;
      hasHScrollBar = needsHScrollBar();
      if( needsVScrollBar() ) {
        hasVScrollBar = true;
        hasHScrollBar = needsHScrollBar();
      }
      getHorizontalBar().setVisible( hasHScrollBar );
      getVerticalBar().setVisible( hasVScrollBar );
    }
  }

  ////////////////////////////
  // Helping methods - various

  @Override
  void notifyResize( Point oldSize ) {
    if( !oldSize.equals( getSize() ) && !TextSizeUtil.isTemporaryResize() ) {
      if( ( style & SWT.VIRTUAL ) != 0 ) {
        checkData();
      }
      clearItemsTextWidths();
      updateScrollBars();
      adjustTopIndex();
    }
    super.notifyResize( oldSize );
  }

  final Point getCheckSize( int index ) {
    Point result = new Point( 0, 0 );
    if( index == 0 && getColumnCount() == 0 ) {
      result = getCheckSize();
    } else {
      int[] columnOrder = getColumnOrder();
      if( columnOrder[ 0 ] == index ) {
        result = getCheckSize();
      }
    }
    return result;
  }

  final Point getCheckSize() {
    Point result = new Point( 0, 0 );
    if( ( style & SWT.CHECK ) != 0 ) {
      Size checkImageSize = getThemeAdapter().getCheckBoxImageSize( this );
      BoxDimensions margin = getCheckBoxMargin();
      result.x = checkImageSize.width + margin.left + margin.right;
      result.y = checkImageSize.height + margin.top + margin.bottom;
    }
    return result;
  }

  final BoxDimensions getCheckBoxMargin() {
    TableThemeAdapter themeAdapter = getThemeAdapter();
    BoxDimensions margin = themeAdapter.getCheckBoxMargin( this );
    if( !margin.equals( CssBoxDimensions.ZERO.dimensions ) ) {
      return margin;
    }
    int checkBoxWidth = themeAdapter.getCheckBoxWidth( this );
    int imageWidth = themeAdapter.getCheckBoxImageSize( this ).width;
    int marginWidth = Math.max( 0, checkBoxWidth - imageWidth );
    int marginLeft = Math.round( marginWidth / 2 );
    return new BoxDimensions( 0, marginLeft, 0, marginLeft );
  }

  /**
   * Returns the scroll-offset of the column, which is the leftOffset unless it is a fixed column.
   */
  final int getColumnLeftOffset( int columnIndex ) {
    int result = leftOffset;
    if( columnIndex >= 0 ) {
      result = isFixedColumn( columnIndex ) ? 0 : leftOffset;
    }
    return result;
  }

  private boolean isFixedColumn( int index ) {
    int[] columnOrder = getColumnOrder();
    int visualIndex = -1;
    for( int i = 0; i < columnOrder.length && visualIndex == -1; i++ ) {
      if( index == columnOrder[ i ] ) {
        visualIndex = i;
      }
    }
    return visualIndex < getFixedColumns();
  }

  private int getFixedColumns() {
    Object fixedColumns = getData( RWT.FIXED_COLUMNS );
    if( fixedColumns instanceof Integer ) {
      if( !( getData( RWT.ROW_TEMPLATE ) instanceof Template ) ) {
        return ( ( Integer )fixedColumns ).intValue();
      }
    }
    return -1;
  }


  final int getVisibleItemCount( boolean includePartlyVisible ) {
    int clientHeight = getClientArea().height - getHeaderHeight();
    int result = 0;
    if( clientHeight >= 0 ) {
      int itemHeight = getItemHeight();
      result = clientHeight / itemHeight;
      if( includePartlyVisible && clientHeight % itemHeight != 0 ) {
        result++;
      }
    }
    return result;
  }

  private void setFocusIndex( int index ) {
    if( index >= 0 && index < itemCount ) {
      focusIndex = index;
    }
  }

  private void removeItem( int index ) {
    TableItem item = items[ index ];
    if( item != null && !item.isDisposed() ) {
      item.dispose();
    } else {
      destroyItem( null, index );
    }
  }

  private void removeFromSelection( int index ) {
    if( index >= 0 && index < itemCount ) {
      boolean found = false;
      for( int i = 0; !found && i < selection.length; i++ ) {
        if( index == selection[ i ] ) {
          int length = selection.length;
          int[] newSel = new int[ length - 1 ];
          System.arraycopy( selection, 0, newSel, 0, i );
          if( i < length - 1 ) {
            System.arraycopy( selection, i + 1, newSel, i, length - i - 1 );
          }
          selection = newSel;
          found = true;
        }
      }
    }
  }

  private void adjustSelectionIdices( int removedIndex ) {
    for( int i = 0; i < selection.length; i++ ) {
      if( selection[ i ] >= removedIndex ) {
        selection[ i ] = selection[ i ] - 1;
      }
    }
  }

  private void adjustTopIndex() {
    int visibleItemCount = getVisibleItemCount( false );
    int correction = visibleItemCount == 0 ? 1 : 0;
    if( topIndex > itemCount - visibleItemCount - correction ) {
      topIndex = Math.max( 0, itemCount - visibleItemCount - correction );
    }
  }

  private void adjustFocusIndex() {
    // Must reset focusIndex before calling getSelectionIndex
    focusIndex = -1;
    focusIndex = getSelectionIndex();
  }

  private void adjustItemIndices( int start ) {
    for( int i = start; i < itemCount; i++ ) {
      if( items[ i ] != null ) {
        items[ i ].index = i;
      }
    }
  }

  boolean isItemVisible( int index ) {
    boolean result = false;
    int visibleItemCount = getVisibleItemCount( true );
    if( visibleItemCount > 0 ) {
      result = index >= topIndex && index < topIndex + visibleItemCount;
    }
    return result;
  }

  private static void sort( int[] items ) {
    /* Shell Sort from K&R, pg 108 */
    int length = items.length;
    for( int gap = length / 2; gap > 0; gap /= 2 ) {
      for( int i = gap; i < length; i++ ) {
        for( int j = i - gap; j >= 0; j -= gap ) {
          if( items[ j ] <= items[ j + gap ] ) {
            int swap = items[ j ];
            items[ j ] = items[ j + gap ];
            items[ j + gap ] = swap;
          }
        }
      }
    }
  }

  private void setTableEmpty() {
    items = new TableItem[ 4 ];
    clearItemImageSize();
  }

  Font getHeaderFont() {
    IControlAdapter controlAdapter = getAdapter( IControlAdapter.class );
    Font result = controlAdapter.getUserFont();
    if( result == null ) {
      result = getThemeAdapter().getHeaderFont( this );
    }
    return result;
  }

  private static int checkStyle( int style ) {
    int result = style;
    if( ( style & SWT.NO_SCROLL ) == 0 ) {
      result |= SWT.H_SCROLL | SWT.V_SCROLL;
    }
    return checkBits( result, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0 );
  }

  boolean needsVScrollBar() {
    int availableHeight = getClientArea().height;
    int height = getHeaderHeight();
    height += getItemCount() * getItemHeight();
    return height > availableHeight;
  }

  boolean needsHScrollBar() {
    boolean result = false;
    int availableWidth = getClientArea().width;
    int columnCount = columnHolder.size();
    if( columnCount > 0 ) {
      int totalWidth = 0;
      for( int i = 0; i < columnCount; i++ ) {
        TableColumn column = columnHolder.getItem( i );
        totalWidth += column.getWidth();
      }
      result = totalWidth > availableWidth;
    } else {
      TableItem measureItem = getMeasureItem();
      if( measureItem != null ) {
        int itemWidth = measureItem.getBounds().width;
        result = itemWidth > availableWidth;
      }
    }
    return result;
  }

  TableItem getMeasureItem() {
    TableItem[] items = tableAdapter.getCachedItems();
    TableItem result = null;
    if( columnHolder.size() == 0 ) {
      // Find item with longest text because the imaginary only column stretches
      // as wide as the longest item (images cannot differ in width)
      for( int i = 0; i < items.length; i++ ) {
        if( result == null ) {
          result = items[ i ];
        } else {
          result = max( result, items[ i ] );
        }
      }
    } else {
      // Take the first item if any
      if( items.length > 0 ) {
        result = items[ 0 ];
      }
    }
    return result;
  }

  private TableItem max( TableItem item1, TableItem item2 ) {
    TableItem result;
    int item1TextWidth = getStringExtent( item1.getFont(), item1.getText( 0 ) ).x;
    int item2TextWidth = getStringExtent( item2.getFont(), item2.getText( 0 ) ).x;
    if( item1TextWidth > item2TextWidth ) {
      result = item1;
    } else {
      result = item2;
    }
    return result;
  }

  Point getStringExtent( Font font, String text ) {
    return stringExtent( font, text, isMarkupEnabledFor( this ) );
  }

  TableThemeAdapter getThemeAdapter() {
    return ( TableThemeAdapter )getAdapter( ThemeAdapter.class );
  }

  ///////////////////
  // Skinning support

  @Override
  void reskinChildren( int flags ) {
    if( items != null ) {
      for( int i = 0; i < items.length; i++ ) {
        TableItem item = items[ i ];
        if( item != null ) {
          item.reskin( flags );
        }
      }
    }
    TableColumn[] columns = getColumns();
    if( columns != null ) {
      for( int i = 0; i < columns.length; i++ ) {
        TableColumn column = columns[ i ];
        if( !column.isDisposed() ) {
          column.reskin( flags );
        }
      }
    }
    super.reskinChildren( flags );
  }
}
