package org.eclipse.swt.widgets;

/*
 * Copyright (c) 2000, 2002 IBM Corp.  All rights reserved.
 * This file is made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 */
 
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.*;
import java.util.Enumeration;
import java.util.Vector;
 
/** 
 * Instances of this class implement a selectable user interface
 * object that displays a list of images and strings and issue
 * notificiation when selected.
 * <p>
 * The item children that may be added to instances of this class
 * must be of type <code>TableItem</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</dd>
 * <dt><b>Events:</b></dt>
 * <dd>Selection, DefaultSelection</dd>
 * </dl>
 * <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>
 */
public class Table extends SelectableItemWidget {
	private static final int COLUMN_RESIZE_OFFSET = 7;	// offset from the start and end of each 
														// column at which the resize cursor is displayed 
														// if the mouse is in the column header
	static final String DOT_STRING = "...";				// used to indicate truncated item labels

	private Header tableHeader;
	private Vector items;
	private Vector columns;
	private boolean drawGridLines = false;
	private boolean firstColumnImage = false;			// true if any item in the first column has an image
	private int columnResizeX;							// last position of the cursor in a column resize operation
	private Cursor columnResizeCursor;					// cursor displayed when a column resize is in progress. 
														// Need to keep reference to the cursor in order to dispose it.
	private boolean isColumnResizeCursor = false;		// set to true if the column resize cursor is active														
	private TableColumn resizeColumn;					// column that is currently being resized
	private TableColumn fillColumn;						// column used to fill up space that is not used 
														// by user defined columns
	private TableColumn defaultColumn;					// Default column that is created as soon as the table is created.
														// Fix for 1FUSJY5
	private int dotsWidth;								// width of the static String dots (see above)
	private int fontHeight;								// font height, avoid use GC.stringExtend for each pain

/**
 * 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 Widget#checkSubclass
 * @see Widget#getStyle
 */
public Table(Composite parent, int style) {
	// use NO_REDRAW_RESIZE to avoid flashing during widget resize redraw
	super(parent, checkStyle(style| SWT.NO_REDRAW_RESIZE));
}

/**
 * Add 'column' to the receiver.
 * @param column - new table column that should be added to 
 *	the receiver
 */
void addColumn(TableColumn column) {
	int index = column.getIndex();
	
	getColumnVector().insertElementAt(column, index);
	// has the column been inserted (vs. appended)?
	if (index < getColumnCount() - 1) {				
		reindexColumns(index + 1);
	}
	// is there more than one user created column?
	// There always is the data and visual of the default column
	// so we don't need to create those for the first user column
	if (getColumnCount() > 1) {
		insertColumnData(column);
	}
	else {								// first user created column
		setContentWidth(0);				// pretend it's ground zero for column resizings
		redraw();						// redraw the table and header. The default column 
		getHeader().redraw();			// won't be drawn anymore, because there now is a user created table.
	}
	insertColumnVisual(column);
}
/**
 * Add 'item' to the receiver.
 * @param item - new table item that should be added to 
 *	the receiver
 * @param index - position the new item should be inserted at
 */
void addItem(TableItem item, int index) {
	Vector items = getItemVector();

	if (index < 0 || index > getItemCount()) {
		error(SWT.ERROR_INVALID_RANGE);
	}	
	addingItem(item, index);
	item.setIndex(index);
	if (index < items.size()) {
		for (int i = index; i < items.size(); i++) {
			TableItem anItem = (TableItem) items.elementAt(i);
			anItem.setIndex(anItem.getIndex() + 1);
		}
		items.insertElementAt(item, index);
	}
	else {
		items.addElement(item);
	}
	addedItem(item, index);
}
/**
 * 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 reciever 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) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener(listener);
	addListener(SWT.Selection,typedListener);
	addListener(SWT.DefaultSelection,typedListener);
}
static int checkStyle (int style) {
	return checkBits (style, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0);
}
protected void checkSubclass () {
	if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
}
/**
 * The width of 'column' is about to change.
 * Adjust the position of all columns behind it.
 */
void columnChange(TableColumn column, Rectangle newBounds) {
	Rectangle columnBounds = column.getBounds();
	Rectangle clientArea = getClientArea();
	int oldXPosition = columnBounds.x + columnBounds.width; 
	int newXPosition = newBounds.x + newBounds.width;
	int widthChange = newBounds.width - columnBounds.width;
	int headerHeight = getHeaderHeight();
	int columnIndex = column.getIndex();

	if (widthChange != 0) {
		getHeader().widthChange(columnIndex, widthChange);
		if (columnIndex != TableColumn.FILL) {
			if (getLinesVisible() == true) {
				oldXPosition -= getGridLineWidth();						// include vertical grid line when scrolling resized column.
				newXPosition -= getGridLineWidth();
			}
			scroll(														// physically move all following columns
				newXPosition, headerHeight, 							// destination x, y
				oldXPosition, headerHeight, 							// source x, y
				clientArea.width, clientArea.height, true);
		}
		column.internalSetBounds(newBounds);
		if (columnIndex != TableColumn.FILL) {
			resetTableItems(columnIndex);
			moveColumns(columnIndex + 1, widthChange);					// logically move all following columns	(set their bounds)
			setContentWidth(getContentWidth() + widthChange);			// set the width of the receiver's content
			claimRightFreeSpace();
			resizeRedraw(column, columnBounds.width, newBounds.width);
		}
	}
}
/**
 * The mouse pointer was double clicked on the receiver.
 * Handle the event according to the position of the mouse click
 * and the modifier key that was pressed, if any.
 * @param event - the mouse event
 */
void columnMouseDoubleClick(Event event) {
	int itemHeight = getItemHeight();
	int itemIndex;
	TableItem hitItem;
	TableColumn hitColumn = getColumnAtX (event.x);
	Event columnDblClickEvent;
	boolean isFullSelection = (getStyle () & SWT.FULL_SELECTION) != 0;

	if (isFocusControl () == false) {
		forceFocus ();
	}
	if (hitColumn != null) {
		itemIndex = (event.y - getHeaderHeight()) / itemHeight + getTopIndex();
		hitItem = (TableItem) getVisibleItem(itemIndex);
		if (hitItem != null && 
			(hitColumn.getIndex() == TableColumn.FIRST || isFullSelection)) {
			if (hitItem.isSelectionHit(event.x) == true) {
				columnDblClickEvent = new Event();
				columnDblClickEvent.item = hitItem;
				notifyListeners(SWT.DefaultSelection, columnDblClickEvent);
			}
		}
	}
}
/**
 * The mouse pointer was pressed down on the receiver.
 * Handle the event according to the position of the mouse click
 * and the modifier key that was pressed, if any.
 * @param event - the mouse event
 */
void columnMouseDown(Event event) {
	int itemHeight = getItemHeight();
	int itemIndex;
	TableItem hitItem;
	TableColumn hitColumn = getColumnAtX (event.x);

	// only react to button one clicks. fixes bug 6770
	if (event.button != 1) {
		return;
	}
	if (isFocusControl () == false) {
		forceFocus ();
	}
	if (hitColumn != null) {
		itemIndex = (event.y - getHeaderHeight()) / itemHeight + getTopIndex();
		hitItem = (TableItem) getVisibleItem(itemIndex);
		if (hitItem != null) {
			if (hitItem.isSelectionHit(event.x) == true) {
				doMouseSelect(hitItem, itemIndex, event.stateMask, event.button);
			}
			else 
			if (hitItem.isCheckHit(new Point(event.x, event.y)) == true) {
				doCheckItem(hitItem);
			}
		}
	}
}
/**
 * The mouse pointer was moved over the receiver.
 * Reset the column resize cursor if it was active.
 * @param event - the mouse event
 */
void columnMouseMove(Event event) {
	if (isColumnResizeStarted() == false) {
		setColumnResizeCursor(false);
	}
}
public Point computeSize(int wHint, int hHint, boolean changed) {
	checkWidget();
	Point size = super.computeSize(wHint, hHint, changed);
	Point headerSize;
	GC gc;
	final int WidthCalculationCount = Math.min(getItemCount(), 50);		// calculate item width for the first couple of items only
	TableItem item;
	Image itemImage;
	String itemText;
	int width;
	int newItemWidth = 0;
		
	if (getHeaderVisible() == true) {
		headerSize = getHeader().computeSize(SWT.DEFAULT, SWT.DEFAULT, false);
		size.y += headerSize.y;		
	}
	if (getContentWidth() == 0 && WidthCalculationCount > 0) {
		gc = new GC(this);
		for (int i = 0; i < WidthCalculationCount; i++) {
			item = getItem(i);
			if (item == null) {
				break;											// no more items
			}
			itemImage = item.getImage();
			itemText = item.getText();
			width = 0;
			if (itemImage != null) {
				width += itemImage.getBounds().width;
			}
			if (itemText != null) {
				width += gc.stringExtent(itemText).x;
			}
			newItemWidth = Math.max(newItemWidth, width);
		}
		if (newItemWidth > 0) {
			size.x = newItemWidth;
		}
		gc.dispose();
	}
	return size;
}
/**
 * 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 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>
 */
public void deselect(int indices[]) {
	checkWidget();
	SelectableItem item = null;
	
	if (indices == null) {
		error(SWT.ERROR_NULL_ARGUMENT);
	}
	for (int i = 0; i < indices.length; i++) {
		item = getVisibleItem(indices[i]);
		if (item != null) {
			deselect(item);
		}
	}
	if (item != null) {
		setLastSelection(item, false);
	}
}
/**
 * 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();
	SelectableItem item = getVisibleItem(index);

	if (item != null) {
		deselect(item);
		setLastSelection(item, false);		
	}
}
/**
 * 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();
	SelectableItem item = null;

	for (int i=start; i<=end; i++) {
		item = getVisibleItem(i);
		if (item != null) {
			deselect(item);
		}
	}
	if (item != null) {
		setLastSelection(item, false);
	}	
}
/**
 * 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();
	
	deselectAllExcept((SelectableItem) null);
}
/**
 * Free resources.
 */
void doDispose() {
	Vector items = getItemVector();
	
	super.doDispose();
	for (int i = items.size() - 1; i >= 0; i--) {
		((TableItem) items.elementAt(i)).dispose();
	}
	setItemVector(null);
	items = getColumnVector();
	while (items.size() > 0) {								// TableColumn objects are removed from vector during dispose()
		((TableColumn) items.lastElement()).dispose();
	}
	resizeColumn = null;
	fillColumn = null;
	defaultColumn = null;
	if (columnResizeCursor != null) {
		columnResizeCursor.dispose();
	}
}
/**
 * Draw a line tracking the current position of a column 
 * resize operation.
 * @param xPosition - x coordinate to draw the line at
 */
void drawColumnResizeLine(int xPosition) {
	GC gc = new GC(this);
	int lineHeight = getClientArea().height;
	int lineWidth = getGridLineWidth();
	
	redraw(getColumnResizeX() - lineWidth, 0, 1, lineHeight, false);
	setColumnResizeX(xPosition);
	gc.drawLine(xPosition - lineWidth, 0, xPosition - lineWidth, lineHeight);
	gc.dispose();
}
/**
 * Draw the grid lines for the receiver.
 * @param event - Paint event triggering the drawing operation.
 * @param drawColumns - The table columns for which the grid 
 *	lines should be drawn.
 */
void drawGridLines(Event event, Enumeration drawColumns) {
	GC gc = event.gc;
	Color oldForeground = getForeground();
	Rectangle columnBounds;
	TableColumn column;
	int lineWidth = getGridLineWidth();
	int itemHeight = getItemHeight();
	int headerHeight = getHeaderHeight();
	int lineXPosition;
	int lineYPosition = headerHeight + ((event.y-headerHeight) / itemHeight) * itemHeight;
	int lineYStopPosition = event.y + event.height;

	gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW));
	// Draw the horizontal lines	
	if (itemHeight > 0) {
		while (lineYPosition < lineYStopPosition) {
			gc.drawLine(
				event.x, lineYPosition + itemHeight - lineWidth, 
				event.x + event.width, lineYPosition + itemHeight - lineWidth);
			lineYPosition += itemHeight; 		
		}
	}
	// Draw the vertical lines at the right border of each column except the fill column
	while (drawColumns.hasMoreElements() == true) {
		column = (TableColumn) drawColumns.nextElement();
		if (column.getIndex() != TableColumn.FILL) {
			columnBounds = column.getBounds();
			lineXPosition = columnBounds.x + columnBounds.width - lineWidth;
			gc.drawLine(
				lineXPosition, event.y, 
				lineXPosition, event.y + event.height);
		}
	}
	gc.setForeground(oldForeground);
}

/**
 * If the receiver has input focus draw a rectangle enclosing 
 * the label of 'item' to indicate the input focus.
 * The rectangle is drawn in either the first column or in all columns 
 * for full row select. 
 * @param item - item for which the selection state should be drawn
 * @param gc - GC to draw on. 
 */
void drawSelectionFocus(TableItem item, GC gc) {
	Point extent = item.getSelectionExtent();
	Point position = new Point(
		item.getImageStopX(TableColumn.FIRST) + getHorizontalOffset(),
		getRedrawY(item));

	gc.drawFocus(position.x, position.y, extent.x, extent.y);
}

/**
 * Returns the column at the given, zero-relative index in the
 * receiver. Throws an exception if the index is out of range.
 * 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>
 */
public TableColumn getColumn(int index) {
	checkWidget();
	Vector columns = getColumnVector();
	
	if (columns == null) error(SWT.ERROR_CANNOT_GET_ITEM);
	if (index < 0 || index >= columns.size()) {
		error(SWT.ERROR_INVALID_RANGE);
	}
	
	return (TableColumn) columns.elementAt(index);
}
/**
 * Return the column located at 'xPosition' in the widget.
 * Return null if xPosition is outside the widget.
 * @param xPosition - position of the desired column
 */
TableColumn getColumnAtX(int xPosition) {
	Enumeration columns = internalGetColumnVector().elements();
	TableColumn column;
	TableColumn hitColumn = null;
	Rectangle bounds;

	while (columns.hasMoreElements() == true && hitColumn == null) {
		column = (TableColumn) columns.nextElement();
		bounds = column.getBounds();
		if ((xPosition >= bounds.x) && 
			(xPosition <= bounds.x + bounds.width)) {
			hitColumn = column;
		}
	}
	if (hitColumn == null) {
		column = getFillColumn();
		bounds = column.getBounds();
		if ((xPosition >= bounds.x) && 
			(xPosition <= bounds.x + bounds.width)) {
			hitColumn = column;
		}
	}
	return hitColumn;
}
/**
 * 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 is 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>
 * @exception SWTError <ul>
 *    <li>ERROR_CANNOT_GET_COUNT - if the operation fails because of an operating system failure</li>
 * </ul>
 */
public int getColumnCount() {
	checkWidget();
	Vector columns = getColumnVector();
	int count = 0;
	
	if (columns != null) {
		count = columns.size();
	}
	return count;
}
/** Replace CURSOR_SIZEWE with real column resize cursor 
 *	(no standard cursor-have to load from file)
 * Answer the cursor displayed during a column resize 
 * operation.
 * Lazy initialize the cursor since it may never be needed.
 */
Cursor getColumnResizeCursor() {
	if (columnResizeCursor == null) {
		columnResizeCursor = new Cursor(getDisplay(), SWT.CURSOR_SIZEWE);
	}
	return columnResizeCursor;
}
/**
 * Answer the current position of the mouse cursor during
 * a column resize operation.
 */
int getColumnResizeX() {
	return columnResizeX;
}
/**
 * Returns an array of <code>TableColumn</code>s which are the
 * columns in the receiver. 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>
 */
public TableColumn [] getColumns() {
	checkWidget();
	Vector columns = getColumnVector();
	TableColumn columnArray[] = new TableColumn[columns.size()];

	columns.copyInto(columnArray);
	return columnArray;
}
/**
 * Answer a Vector containing all columns of receiver except 
 * the fill column to the right of all content columns.
 */
Vector getColumnVector() {
	return columns;
}
/**
 * Return the default column that is created as soon as the table 
 * is created.
 * Fix for 1FUSJY5
 */
TableColumn getDefaultColumn() {
	return defaultColumn;
}
/**
 * Answer the width of the replacement String used to indicate 
 * truncated items.
 * Cached to speed up calculation of truncated items.
 * @param gc - GC used to measure the width of the replacement 
 *	String
 */
int getDotsWidth(GC gc) {
	return dotsWidth;
}
/**
 * Answer the column used to occupy any space left to the 
 * right of all the user created columns.
 */
TableColumn getFillColumn() {
	return fillColumn;
}
/**
 * Returns the width in pixels of a grid line.
 *
 * @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 1;
}
/**
 * Answer the table header widget.
 */
Header getHeader() {
	return tableHeader;
}
/**
 * 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>
 * 
 * @since 2.0 
 */
public int getHeaderHeight() {
	checkWidget();
	Header header = getHeader();
	int height = 0;
	
	if (header.getVisible() == true) {
		height = header.getBounds().height;
	}
	return height;
}
/**
 * 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 getHeader().getVisible();
}
/**
 * Answer the image extent of 'item'. Use the image of any column.
 */
Point getImageExtent(SelectableItem item) {
	Image image = null;
	Rectangle imageBounds;
	Point imageExtent = null;
	int columnCount = internalGetColumnCount();

	for (int i = 0; i < columnCount && image == null; i++) {
		image = ((TableItem) item).getImage(i);
	}		
	if (image != null) {
		imageBounds = image.getBounds();
		imageExtent = new Point(imageBounds.width, imageBounds.height);
	}
	return imageExtent;
}
/**
 * Answer the index of 'item' in the receiver.
 */
int getIndex(SelectableItem item) {
	int index = -1;
	
	if (item != null && item.getSelectableParent() == this) {
		index = ((TableItem) item).getIndex();
	}
	return index;
}
/**
 * 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 (!(0 <= index && index < getItemCount())) {
		error(SWT.ERROR_INVALID_RANGE);
	}		
	return (TableItem) getVisibleItem(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.
 *
 * @param point the point used to locate the item
 * @return the item at the given point
 *
 * @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>
 */
public TableItem getItem(Point point) {
	int headerHeight = getHeaderHeight();
	TableColumn column = getColumnAtX(point.x);
	TableItem item = null;

	if (column != null && column.getIndex() != TableColumn.FILL && point.y - headerHeight > 0) {
		int itemIndex = (point.y - headerHeight) / getItemHeight() + getTopIndex();
		item = (TableItem) getVisibleItem(itemIndex);
		if (item != null) {
			Point itemSize = item.getItemExtent(column);
			if (point.x - column.getBounds().x > itemSize.x) {
				item = null;
			}
		}
	}
	return item;
}
/**
 * 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 getItemVector().size();
}
/**
 * Answer the number of items that can be displayed in the
 * client area of the receiver without truncating any items.
 */
int getItemCountWhole() {
	int clientAreaHeight = Math.max(0, getClientArea().height - getHeaderHeight());
	
	return clientAreaHeight / getItemHeight();
}
/**
 * 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();
	
	return super.getItemHeight();
}
/**
 * Answer the number of pixels that should be added to the item height.
 */
int getItemPadding() {
	return getGridLineWidth() + getDisplay().textHighlightThickness + 1;
}
/**
 * Returns an 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();
	Vector items = getItemVector();
	TableItem itemArray[] = new TableItem[items.size()];

	items.copyInto(itemArray);
	return itemArray;
}
/**
 * Answer all items of the receiver.
 */
Vector getItemVector() {
	return items;
}
/**
 * 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 drawGridLines;
}
/** 
 * Answer a Vector containing the columns that need repainting 
 * based on the 'paintArea'.
 * @param paintArea - invalidated rectangle that needs repainting
 */
Vector getPaintColumns(Rectangle paintArea) {
	Enumeration columns = internalGetColumnVector().elements();
	Vector paintColumns = new Vector();
	TableColumn column;
	Rectangle columnBounds;
	int paintAreaRightBorder = paintArea.x + paintArea.width;

	while (columns.hasMoreElements() == true) {
		column = (TableColumn) columns.nextElement();
		columnBounds = column.getBounds();
		if ((columnBounds.x + columnBounds.width >= paintArea.x) &&	// does the paintArea overlap the current column?
			(columnBounds.x <= paintAreaRightBorder)) {
			paintColumns.addElement(column);
		}
	}
	return paintColumns;
}
/** 
 * Return the width of the widest item in the column identified by 'columnIndex'
 * @param columnIndex - index of the column whose preferred width should be
 *	calculated
 */
int getPreferredColumnWidth(int columnIndex) {
	Enumeration tableItems = getItemVector().elements();
	TableItem tableItem;
	int width = 0;
	int headerWidth;
	
	if (columnIndex != TableColumn.FILL) {
		while (tableItems.hasMoreElements() == true) {
			tableItem = (TableItem) tableItems.nextElement();
			width = Math.max(width, tableItem.getPreferredWidth(columnIndex));
		}
		headerWidth = getHeader().getPreferredWidth(columnIndex);
		if (width < headerWidth) {
			width = headerWidth;
		}
	}
	return width;
}
/**
 * Answer the position in the receiver where 'item' is drawn
 * @return the y coordinate at which 'item' is drawn.
 *	Return -1 if 'item' is not an item of the receiver 
 */
int getRedrawY(SelectableItem item) {
	int redrawY = super.getRedrawY(item);

	if (redrawY != -1) {
		redrawY += getHeaderHeight();
	}
	return redrawY;
}
/**
 * Answer the column that is being resized or null if no 
 * resize operation is in progress.
 */
TableColumn getResizeColumn() {
	return resizeColumn;
}
/**
 * Return the positions at which the column identified by 'columnIndex' 
 * must be redrawn.
 * These positions may be different for each item since each item may 
 * have a different label
 * @param columnIndex - the column index
 * @param columnWidth - width of the column
 * @return the positions at which the column must be redrawn.
 *	Each item in the widget client area is represented by a slot in 
 * 	the array. The item at position 'topIndex' is the first item in 
 *	the array.
 */
int [] getResizeRedrawX(int columnIndex, int columnWidth) {
	int topIndex = getTopIndex();
	int bottomIndex = getBottomIndex();
	int resizeRedrawX[];
	TableItem item;

	bottomIndex = Math.min(bottomIndex, getItemCount());
	resizeRedrawX = new int[bottomIndex-topIndex+1];
	for (int i = topIndex; i < bottomIndex; i++) {
		item = (TableItem) getVisibleItem(i);
		resizeRedrawX[i-topIndex] = item.getDotStartX(columnIndex, columnWidth);
	}
	return resizeRedrawX;
}
/**
 * Returns an array of <code>TableItem</code>s that are currently
 * selected in the receiver. 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();
	Vector selectionVector = getSelectionVector();
	TableItem[] selectionArray = new TableItem[selectionVector.size()];

	selectionVector.copyInto(selectionArray);
	sort(selectionArray, 0, selectionArray.length);
	return selectionArray;
}

/**
 * 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 super.getSelectionCount();
}

int getFontHeight(){
	return fontHeight;
}
/**
 * Answer the size of the full row selection rectangle for 'item'.
 */
Point getFullSelectionExtent(TableItem item) {
	TableColumn lastColumn = (TableColumn) internalGetColumnVector().lastElement();
	Point selectionExtent = null;
	Rectangle columnBounds;
	int xPosition = item.getImageStopX(TableColumn.FIRST);
	int gridLineWidth = getGridLineWidth();

	if (lastColumn != null) {
		columnBounds = lastColumn.getBounds();
		selectionExtent = new Point(
			columnBounds.x - getHorizontalOffset() + columnBounds.width - xPosition - gridLineWidth, 
			getItemHeight());
		if (getLinesVisible() == true) {
			selectionExtent.y -= gridLineWidth;
		}	
	}
	return selectionExtent;
}
/**
 * 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 index = -1;
	
	if (getSelectionCount() > 0) {
		index = getIndex(getSelection()[0]);
	}
	return index;
}
/**
 * Returns the zero-relative indices of the items which are currently
 * selected in the receiver.  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();
	TableItem[] items = getSelection();
	int indices[] = new int[items.length];

	for (int i = 0; i < items.length; i++) {
		indices[i] = getIndex(items[i]);
	}	
	return indices;
}
/**
 * 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 super.getTopIndex();
}
/**
 * Answer the index of 'item' in the receiver.
 * Answer -1 if the item is not visible.
 * The returned index must refer to a visible item.
 * Note: 
 * 	Visible in this context does not neccessarily mean that the 
 * 	item is displayed on the screen. It only means that the item 
 * 	would be displayed if it is located inside the receiver's 
 * 	client area.
 *	Every item in a table widget should be visible.
 */
int getVisibleIndex(SelectableItem item) {
	return getIndex(item);
}
/**
 * Answer the SelectableItem located at 'itemIndex' in the receiver.
 * @param itemIndex - location of the SelectableItem object to return
 */
SelectableItem getVisibleItem(int itemIndex) {
	Vector items = getItemVector();
	TableItem item = null;
	
	if ((items != null) && (itemIndex >= 0) && (itemIndex < items.size())) {
		item = (TableItem) items.elementAt(itemIndex);
	}
	return item;
}
/**
 * Answer the y coordinate at which 'item' is drawn. 
 * @param item - SelectableItem for which the paint position 
 *	should be returned
 * @return the y coordinate at which 'item' is drawn.
 *	Return -1 if 'item' is null or outside the client area
 */
int getVisibleRedrawY(SelectableItem item) {
	int redrawY = -1;
	int index = getTopIndex();
	int bottomIndex = getBottomIndex();
	
	if (item == null) {
		return redrawY;
	}
	while (index < bottomIndex && item.equals(getVisibleItem(index)) == false) {
		index++;
	}
	if (index < bottomIndex) {
		redrawY = getRedrawY(item);
	}
	return redrawY;
}
/**
 * Handle the events the receiver is listening to.
 */
void handleEvents(Event event) {
	switch (event.type) {
		case SWT.MouseMove:
			if (event.widget == tableHeader) {
				headerMouseMove(event);
			}
			else {
				columnMouseMove(event);
			}
			break;
		case SWT.MouseDown:
			if (event.widget == tableHeader) {
				headerMouseDown(event);
			}
			else {
				columnMouseDown(event);
			}
			break;
		case SWT.MouseDoubleClick:
			columnMouseDoubleClick(event);
			break;
		case SWT.MouseUp:
			mouseUp(event);
			break;
		case SWT.Paint:
			paint(event);
			break;
		default:
			super.handleEvents(event);
	}		
}
/**
 * Answer true if any item in the first column has an image.
 * Answer false otherwise.
 */
boolean hasFirstColumnImage() {
	return firstColumnImage;
}
/**
 * The mouse pointer was pressed down on the receiver's header
 * widget. Start a column resize operation if apropriate.
 * @param event - the mouse event that occured over the header 
 *	widget
 */
void headerMouseDown(Event event) {
	TableColumn column = getColumnAtX(event.x);

	// only react to button one clicks. fixes bug 6770
	if (event.button != 1) {
		return;
	}
	if (isColumnResize(event) == true) {
		startColumnResize(event);
	}
	else
	if (column != null) {
		column.notifyListeners(SWT.Selection, new Event());
	}
}
/**
 * The mouse pointer was moved over the receiver's header widget.
 * If a column is currently being resized a vertical line indicating 
 * the new position of the resized column is drawn.
 * Otherwise, if no column resize operation is in progress, the 
 * column resize cursor is displayed when the mouse is near the border 
 * of a column.
 */
void headerMouseMove(Event event) {
	if (isColumnResizeStarted() == false) {				// only check whether cursor is in resize
		setColumnResizeCursor(isColumnResize(event));	// area if no resize operation is in progress
	}
	else 
	if (event.x >= getResizeColumn().getBounds().x) {
		drawColumnResizeLine(event.x);
		update();										// looks better if resize line is drawn immediately
	}
}
/**
 * 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 column 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 column) {
	checkWidget();

	if (column == null) {
		error(SWT.ERROR_NULL_ARGUMENT);
	}
	return internalGetColumnVector().indexOf(column);
}
/**
 * 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) {
		error(SWT.ERROR_NULL_ARGUMENT);
	}	
	return getIndex(item);
}
/**
 * Initialize the receiver. Create a header widget and an empty column.
 */
void initialize() {
	columns = new Vector();
	setItemVector(new Vector());
	GC gc = new GC(this);
	Point extent = gc.stringExtent(DOT_STRING);
	dotsWidth = extent.x;
	fontHeight = extent.y;
	gc.dispose();
	tableHeader = new Header(this);
	tableHeader.setVisible(false);					// SWT table header is invisible by default, too
	fillColumn = TableColumn.createFillColumn(this);
	setColumnPosition(fillColumn);
	defaultColumn = TableColumn.createDefaultColumn(this);	// Create the default column. Fix for 1FUSJY5	
	super.initialize();
}
/**
 * Insert the new column 'column' into the table data at position 
 * 'index'.
 */
void insertColumnData(TableColumn column) {
	Enumeration tableItems = getItemVector().elements();
	TableItem tableItem;
	
	while (tableItems.hasMoreElements() == true ) {
		tableItem = (TableItem) tableItems.nextElement();
		tableItem.insertColumn(column);
	}
}
/**
 * Insert the new column 'column'.
 * Set the position and move the following columns to the right.
 */
void insertColumnVisual(TableColumn column) {
	Rectangle columnBounds = column.getBounds();
	Rectangle previousColumnBounds;
	int index = column.getIndex();
		
	if (index > 0) {
		previousColumnBounds = getColumn(index - 1).getBounds();
		columnBounds.x = previousColumnBounds.x + previousColumnBounds.width;
	}
	else {
		columnBounds.x = 0;
	}
	column.setBounds(columnBounds);
	setColumnPosition(column);
}
/**
 * Set event listeners for the receiver.
 */
void installListeners() {
	Header tableHeader = getHeader();
	Listener listener = getListener();

	super.installListeners();	
	tableHeader.addListener(SWT.MouseMove, listener);
	tableHeader.addListener(SWT.MouseDown, listener);
	tableHeader.addListener(SWT.MouseUp, listener);
	
	addListener(SWT.MouseMove, listener);
	addListener(SWT.MouseDown, listener);
	addListener(SWT.MouseDoubleClick, listener);
	addListener(SWT.MouseUp, listener);
	addListener(SWT.Paint, listener);
}
/**
 * Answer the TableColumn at 'index'.
 * If the user has not created any columns the default column is 
 * returned if index is 0.
 * Fix for 1FUSJY5 
 */
TableColumn internalGetColumn(int index) {
	Vector columns = internalGetColumnVector();
	
	if (columns == null) error(SWT.ERROR_CANNOT_GET_ITEM);
	if (index < 0 || index >= columns.size()) {
		error(SWT.ERROR_INVALID_RANGE);
	}
	
	return (TableColumn) columns.elementAt(index);

}
/**
 * Answer the number of columns in the receiver.
 * If the user has not created any columns, 1 is returned since there 
 * always is a default column.
 * Fix for 1FUSJY5
 */
int internalGetColumnCount() {
	Vector columns = internalGetColumnVector();
	int count = 0;
	
	if (columns != null) {
		count = columns.size();
	}
	return count;
}
/**
 * Return a Vector containing all columns of the receiver except 
 * the fill column to the right of all content columns.
 * Return a Vector containing the default column if the user has
 * not created any columns.
 * Fix for 1FUSJY5 
 */
Vector internalGetColumnVector() {
	Vector internalColumnVector;
	TableColumn defaultColumn;
	
	if (columns.isEmpty() == false) {
		internalColumnVector = columns;
	}
	else {
		internalColumnVector = new Vector(1);
		defaultColumn = getDefaultColumn();		
		if (defaultColumn != null) {
			internalColumnVector.addElement(defaultColumn);
		}
	}
	return internalColumnVector;
}
/**
 * Answer whether the mouse pointer is at a position that can
 * start a column resize operation. A column resize can be 
 * started if the mouse pointer is at either the left or right 
 * border of a column.
 * @param event - mouse event specifying the location of the 
 *	mouse pointer.
 */
boolean isColumnResize(Event event) {
	TableColumn hotColumn = getColumnAtX(event.x);
	if (hotColumn == null) return false;
	Rectangle bounds = hotColumn.getBounds();
	int hotColumnIndex = hotColumn.getIndex();
	int columnX = event.x - bounds.x;
	boolean isColumnResize = false;

	if (columnX <= COLUMN_RESIZE_OFFSET && 									// mouse over left side of column? and
		hotColumnIndex != TableColumn.FIRST) {								// it's not the first column)
		if (hotColumnIndex == TableColumn.FILL) {
			hotColumn = (TableColumn) internalGetColumnVector().lastElement();
		}
		else {
			hotColumn = internalGetColumn(hotColumnIndex - 1);
		}
		isColumnResize = hotColumn.getResizable();							// check whether left column can be resized
	}
	else
	if (columnX >= bounds.width - COLUMN_RESIZE_OFFSET && 					// mouse over right side of column and
		hotColumn != getFillColumn()) {										// column is a real one (not the right hand fill column)?
		isColumnResize = hotColumn.getResizable();							// check whether column under cursor can be resized
	}
	return isColumnResize;
}
/**
 * Answer whether a column of the receiver is being resized.
 */
boolean isColumnResizeStarted() {
	return (getResizeColumn() != null);
}
/**
 * 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();
	TableItem item = getItem(index);

	return (item != null && item.isSelected() == true);
}
/**
 * 'changedItem' has changed. Update the default column width.
 * @param changedItem - the item that has changed
 */
void itemChanged(SelectableItem changedItem, int repaintStartX, int repaintWidth) {
	// call super.itemChanged first to make sure that table image size is 
	// calculated if necessary. Fixes 1FYPBBG.
	super.itemChanged(changedItem, repaintStartX, repaintWidth);
	// remember if any item ever had an image in the first column.
	if (firstColumnImage == false && changedItem.getImage() != null) {
		firstColumnImage = true;
		redraw ();
	}
	setFirstColumnWidth((TableItem) changedItem);	
}
/**
 * A mouse button was released. 
 * Update the display if a column has been resized.
 * @param event - the mouse event for the button up action
 */
void mouseUp(Event event) {
	TableColumn resizeColumn = getResizeColumn();
	Rectangle oldColumnBounds;
	int resizeXPosition;
	int widthChange;
	if (isColumnResizeStarted() == true) {
		oldColumnBounds = resizeColumn.getBounds();
		resizeXPosition = getColumnResizeX();	
		widthChange = resizeXPosition - (oldColumnBounds.x + oldColumnBounds.width);
		if (widthChange >= 0) {
			redraw(resizeXPosition - getGridLineWidth(), 0, 1, getClientArea().height, false);		// remove resize line
			update();															// to avoid cheese caused by scrolling the resize line
		}
		if (widthChange != 0) {
			resizeColumn.setWidth(oldColumnBounds.width + widthChange);
		}
		setResizeColumn(null);
	}
}
/**
 * Adjust the position of all columns starting at 'startIndex'.
 * @param startIndex - index at which the column move should begin
 *	If this is the index of the fill column all columns are moved,
 * 	including the fill column
 * @param moveDistance - distance that the columns should be moved.
 *	< 0 = columns are going to be moved left.
 *	> 0 = columns are going to be moved right.
 */
void moveColumns(int startIndex, int moveDistance) {
	Vector columns = internalGetColumnVector();
	TableColumn moveColumn;
	Rectangle columnBounds;

	if (startIndex == TableColumn.FILL) {
		moveColumn = getFillColumn();
		columnBounds = moveColumn.getBounds();
		columnBounds.x += moveDistance;
		moveColumn.setBounds(columnBounds);
		startIndex = 0;					// continue with first data column
	}
	for (int i = startIndex; i < columns.size(); i++) {
		moveColumn = (TableColumn) columns.elementAt(i);
		columnBounds = moveColumn.getBounds();
		columnBounds.x += moveDistance;
		moveColumn.setBounds(columnBounds);
	}
}
/**
 * Adjust the y position of all columns including the fill column.
 */
void moveColumnsVertical() {
	Enumeration columns = internalGetColumnVector().elements();
	TableColumn column;

	setColumnPosition(getFillColumn());
	while (columns.hasMoreElements() == true) {
		column = (TableColumn) columns.nextElement();
		setColumnPosition(column);
	}
}
/** 
 * A paint event has occurred. Paint the invalidated items.
 * @param event - paint event specifying the invalidated area.
 */
void paint(Event event) {
	int visibleRange[];
	int headerHeight = getHeaderHeight();
	Vector paintColumns = getPaintColumns(event.getBounds());
	TableItem focusItem = null;
	
	if (paintColumns.size() > 0) {
		event.y -= headerHeight;
		visibleRange = getIndexRange(event.getBounds());
		event.y += headerHeight;
		// When the top index is > 0 and the receiver is resized 
		// higher so that the top index becomes 0 the invalidated 
		// rectangle doesn't start below the header widget but at 
		// y position 0. Subtraction of the header height (it is 
		// not above the receiver but on top) causes event.y and 
		// subsequently visibleRange[0] to be negative.
		// Hack to prevent visibleRange[0] from becoming negative.
		// Need to find out why the invalidated area starts at 0
		// in the first place.
		if (visibleRange[0] < 0) {
			visibleRange[0] = 0;
		}
		// 
		visibleRange[1] = Math.min(visibleRange[1], getItemCount()-1-getTopIndex());
		focusItem = paintItems(event, visibleRange[0], visibleRange[1], paintColumns);
	}
	if (getLinesVisible() == true) {
		drawGridLines(event, paintColumns.elements());
	}
	if (focusItem != null) {
		// draw focus on top of drawing grid lines so that focus rectangle 
		// is not obscured by grid. Fixes 1G5X20B
		drawSelectionFocus(focusItem, event.gc);	
	}
}

/**
 * Paint items of the receiver starting at index 'topPaintIndex' and 
 * ending at 'bottomPaintIndex'.
 * @param event - holds the GC to draw on and the clipping rectangle
 * @param topPaintIndex - index of the first item to draw
 * @param bottomPaintIndex - index of the last item to draw
 * @param paintColumns - the table columns that should be painted
 * @return the item that has focus if it was among the rendered items.
 *	null if the focus item was not rendered or if no item has focus (ie. 
 *	because the widget does not have focus)
 */
TableItem paintItems(Event event, int topPaintIndex, int bottomPaintIndex, Vector paintColumns) {
	Enumeration columns;
	TableColumn column;
	TableItem paintItem;
	TableItem focusItem = null;
	Point selectionExtent;
	GC gc = event.gc;
	Color selectionColor = getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION);
	Point fullSelectionExtent;	
	int paintXPosition;
	int paintYPosition;
		
	topPaintIndex += getTopIndex();
	bottomPaintIndex += getTopIndex();
	for (int i = topPaintIndex; i <= bottomPaintIndex; i++) {
		paintItem = (TableItem) getVisibleItem(i);
		paintXPosition = paintItem.getSelectionX();
		paintYPosition = getRedrawY(paintItem);
		fullSelectionExtent = getFullSelectionExtent(paintItem);
		gc.setBackground(paintItem.getBackground());
		gc.fillRectangle(paintXPosition, paintYPosition, fullSelectionExtent.x, fullSelectionExtent.y);
		
		if (paintItem.isSelected() == true) {
			selectionExtent = paintItem.getSelectionExtent();
			gc.setBackground(selectionColor);
			gc.fillRectangle(paintXPosition, paintYPosition, selectionExtent.x, selectionExtent.y);
		} 
		columns = paintColumns.elements(); 
		while (columns.hasMoreElements() == true) {
			column = (TableColumn) columns.nextElement();
			paintSubItem(event, paintItem, column, paintYPosition);
		}
		if (hasFocus(paintItem)) {
			focusItem = paintItem;
		}
	}
	return focusItem;
}

/**
 * Paint the table item 'paintItem' in 'column' at y position 
 * 'paintYPosition' of the receiver.
 * @param event - holds the GC to draw on and the clipping 
 *	rectangle.
 * @param paintItem - the item to draw
 * @param column - column to draw 'paintItem' in
 * @param paintYPosition - y position in the receiver to draw 
 *	'paintItem' at.
 */
void paintSubItem(Event event, TableItem paintItem, TableColumn column, int paintYPosition) {
	Rectangle columnBounds = column.getBounds();
	Point paintPosition;
	int gridLineWidth = getGridLineWidth();
	int itemDrawStopX = columnBounds.x + columnBounds.width - gridLineWidth;
	int clipX;
	
	if (event.x + event.width > itemDrawStopX) {	// does the invalidated area stretch past the current column's right border?
		clipX = Math.max(columnBounds.x, event.x);
		event.gc.setClipping(											// clip the drawing area
			clipX, event.y, 
			Math.max(0, itemDrawStopX - clipX), event.height);		
	}
	paintPosition = new Point(columnBounds.x, paintYPosition);
	paintItem.paint(event.gc, paintPosition, column);
	if (event.x + event.width > itemDrawStopX) {
		event.gc.setClipping(event.x, event.y, event.width, event.height); // restore original clip rectangle
	}
}
/**
 * Reindex all columns starting at 'startIndex'.
 * Reindexing is necessary when a new column has been inserted.
 */
void reindexColumns(int startIndex) {
	Vector columns = getColumnVector();
	TableColumn column;
	
	for (int i = startIndex; i < getColumnCount(); i++) {
		column = (TableColumn) columns.elementAt(i);
		column.setIndex(i);
	}
}
/**
 * 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>
 * </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>
 * @exception SWTError <ul>
 *    <li>ERROR_ITEM_NOT_REMOVED - if the operation fails because of an operating system failure</li>
 * </ul>
 */
public void remove(int indices[]) {
	checkWidget();
	SelectableItem item;
	int [] sortedIndices;
	int last = -1;
	int sortedIndex;
	
	if (indices == null) {
		error(SWT.ERROR_NULL_ARGUMENT);
	}
	sortedIndices = new int[indices.length];	
	System.arraycopy (indices, 0, sortedIndices, 0, indices.length);
	sort(sortedIndices);								// sort indices in descending order
	for (int i = 0; i < sortedIndices.length; i++) {
		sortedIndex = sortedIndices[i];
		if (sortedIndex != last) {
			item = getVisibleItem(sortedIndex);
			if (item != null) {
				item.dispose();
			}
			else {
				if (0 <= sortedIndex && sortedIndex < getItemVector().size()) {
					error(SWT.ERROR_ITEM_NOT_REMOVED);
				} 
				else {
					error(SWT.ERROR_INVALID_RANGE);
				}          
			}
			last = sortedIndex;
		}
	}
}
/**
 * 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>
 * @exception SWTError <ul>
 *    <li>ERROR_ITEM_NOT_REMOVED - if the operation fails because of an operating system failure</li>
 * </ul>
 */
public void remove(int index) {
	checkWidget();
	SelectableItem item = getVisibleItem(index);

	if (item != null) {
		item.dispose();
	}
	else {
		if (0 <= index && index < getItemVector().size()) {
			error(SWT.ERROR_ITEM_NOT_REMOVED);
		} 
		else {
			error(SWT.ERROR_INVALID_RANGE);
		}          
	}
}
/**
 * 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>
 * @exception SWTError <ul>
 *    <li>ERROR_ITEM_NOT_REMOVED - if the operation fails because of an operating system failure</li>
 * </ul>
 */
public void remove(int start, int end) {
	checkWidget();
	SelectableItem item;
	
	for (int i = end; i >= start; i--) {
		item = getVisibleItem(i);
		if (item != null) {
			item.dispose();
		}
		else {
			error(SWT.ERROR_ITEM_NOT_REMOVED);
		}
	}
}
/**
 * Removes all of the items from the receiver.
 * <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>
 */
public void removeAll() {
	checkWidget();
	Vector items = getItemVector();

	setRedraw(false);
	setRemovingAll(true);
	for (int i = items.size() - 1; i >= 0; i--) {
		((TableItem) items.elementAt(i)).dispose();
	}
	setItemVector(new Vector());
	reset();
	calculateVerticalScrollbar();
	setRemovingAll(false);
	setRedraw(true);	
}
/**
 * Remove 'column' from the receiver.
 */
void removeColumn(TableColumn column) {
	int index = column.getIndex();
	int columnWidth = column.getWidth();
	int columnCount;

	if (isRemovingAll() == true) {
		getColumnVector().removeElementAt(index);
	}
	else {		
		getColumnVector().removeElementAt(index);
		columnCount = getColumnCount();
		// Never remove the data of the last user created column. 
		// SWT for Windows does the same.
		if (columnCount > 0) {
			removeColumnData(column);
			removeColumnVisual(column);		
		}
		else {
			redraw();
			getHeader().redraw();
		}
		if (index < columnCount) {					// is there a column after the removed one?
			reindexColumns(index);
		}
		// last user created column is about to be removed.
		if (columnCount == 0) {		
			TableColumn defaultColumn = getDefaultColumn();
			defaultColumn.pack();						// make sure the default column has the right size...
			setColumnPosition(defaultColumn);			// ...and is at the right position
		}
		// Fixes for 1G1L0UT
		// Reduce the content width by the width of the removed column
		setContentWidth(getContentWidth() - columnWidth);
		// claim free space
		claimRightFreeSpace();		
		//
	}
}
/**
 * Remove the column 'column' from the table data.
 */
void removeColumnData(TableColumn column) {
	Enumeration tableItems = getItemVector().elements();
	TableItem tableItem;

	while (tableItems.hasMoreElements() == true ) {
		tableItem = (TableItem) tableItems.nextElement();
		tableItem.removeColumn(column);
	}
}
/**
 * Remove the column 'column'.
 * Set the position of the following columns.
 */
void removeColumnVisual(TableColumn column) {
	int columnWidth = column.getWidth();
		
	// move following columns to the left
	moveColumns(column.getIndex(), columnWidth * -1);
	redraw();
	getHeader().redraw();
}
/** 
 * Remove 'item' from the receiver. 
 * @param item - item that should be removed from the receiver
 */
void removeItem(TableItem item) {
	if (isRemovingAll() == true) return;
	
	Vector items = getItemVector();
	int index = items.indexOf(item);
	if (index != -1) {		
		removingItem(item);				
		items.removeElementAt(index);
		for (int i = index; i < items.size(); i++) {
			TableItem anItem = (TableItem) items.elementAt(i);
			anItem.setIndex(anItem.getIndex() - 1);
		}		
		removedItem(item);		
	}
}
/**
 * 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
 */
public void removeSelectionListener(SelectionListener listener) {
	checkWidget();
	if (listener == null) {
		error(SWT.ERROR_NULL_ARGUMENT);
	}
	removeListener(SWT.Selection, listener);
	removeListener(SWT.DefaultSelection, listener);
}
/** 
 * Reset cached data of column at 'columnIndex' for the items of the receiver. 
 * @param columnIndex - index of the column for which the item data should be 
 *	reset.
 */
void resetTableItems(int columnIndex) {
	Enumeration tableItems = getItemVector().elements();
	TableItem tableItem;

	while (tableItems.hasMoreElements() == true ) {
		tableItem = (TableItem) tableItems.nextElement();
		tableItem.reset(columnIndex);
	}
}
/**
 * The receiver has been resized. Resize the fill column 
 * and the header widget.
 */
void resize(Event event) {
	TableColumn fillColumn = getFillColumn();
	Rectangle fillColumnBounds;

	super.resize(event);
	// the x position may change in super.resize.
	// get the column bounds after calling super.resize. Fixes 1G7ALGG
	fillColumnBounds = fillColumn.getBounds();
	fillColumnBounds.width = Math.max(0, getClientArea().width - getContentWidth());
	fillColumn.setBounds(fillColumnBounds);
	resizeHeader();
}
/**
 * Resize the header widget to occupy the whole width of the
 * receiver.
 */
void resizeHeader() {
	Header tableHeader = getHeader();
	Point size = tableHeader.getSize();

	size.x = Math.max(getContentWidth(), getClientArea().width);
	tableHeader.setSize(size);
}
/**
 * Redraw 'column' after its width has been changed.
 * @param column - column whose width has changed.
 * @param oldColumnWidth - column width before resize
 * @param oldColumnWidth - column width after resize 
 */
void resizeRedraw(TableColumn column, int oldColumnWidth, int newColumnWidth) {
	Rectangle columnBounds = column.getBounds();
	int columnIndex = column.getIndex();
	int oldRedrawStartX[] = getResizeRedrawX(columnIndex, oldColumnWidth);
	int newRedrawStartX[] = getResizeRedrawX(columnIndex, newColumnWidth);
	int itemHeight = getItemHeight();
	int widthChange = newColumnWidth - oldColumnWidth;
	int topIndex = getTopIndex();

	for (int i = 0; i < newRedrawStartX.length; i++) {
		if (newRedrawStartX[i] != oldRedrawStartX[i]) {
			if (widthChange > 0) {
				newRedrawStartX[i] = oldRedrawStartX[i];
			}
			redraw(
				columnBounds.x + newRedrawStartX[i], columnBounds.y + itemHeight * (i + topIndex), 
				columnBounds.width - newRedrawStartX[i], itemHeight, false);
		}
	}
}
/**
 * Scroll horizontally by 'numPixel' pixel.
 * @param numPixel - the number of pixel to scroll
 *	< 0 = columns are going to be moved left.
 *	> 0 = columns are going to be moved right.
 */
void scrollHorizontal(int numPixel) {
	Rectangle clientArea = getClientArea();	

	scroll(
		numPixel, 0, 								// destination x, y
		0, 0, 										// source x, y
		clientArea.width, clientArea.height, true);
	getHeader().scroll(
		numPixel, 0, 								// destination x, y
		0, 0, 										// source x, y
		clientArea.width, clientArea.height, true);
	moveColumns(TableColumn.FILL, numPixel);
}
/**
 * Scroll vertically by 'scrollIndexCount' items.
 * @param scrollIndexCount - the number of items to scroll.
 *	scrollIndexCount > 0 = scroll up. scrollIndexCount < 0 = scroll down
 */
void scrollVertical(int scrollIndexCount) {
	int scrollAmount = scrollIndexCount * getItemHeight();
	int headerHeight = getHeaderHeight();
	int destY;
	int sourceY;
	boolean scrollUp = scrollIndexCount < 0;
	Rectangle clientArea = getClientArea();

	if (scrollIndexCount == 0) {
		return;
	}
	if (scrollUp == true) {
		destY = headerHeight - scrollAmount;
		sourceY = headerHeight;
	}
	else {
		destY = headerHeight;
		sourceY = destY + scrollAmount;
	}
	scroll(
		0, destY, 									// destination x, y
		0, sourceY,									// source x, y
		clientArea.width, clientArea.height, true);
}
/**
 * Scroll items down to make space for a new item added to 
 * the receiver at position 'index'.
 * @param index - position at which space for one new item
 *	should be made. This index is relative to the first item 
 *	of the receiver.
 */
void scrollVerticalAddingItem(int index) {
	int itemHeight = getItemHeight();
	int sourceY = getHeaderHeight();
	Rectangle clientArea = getClientArea();	

	if (index >= getTopIndex()) {
		sourceY += (index-getTopIndex()) * itemHeight;
	}
	scroll(
		0, sourceY + itemHeight, 				// destination x, y
		0, sourceY,								// source x, y
		clientArea.width, clientArea.height, true);
}
/**
 * Scroll the items below the item at position 'index' up 
 * so that they cover the removed item.
 * @param index - index of the removed item
 */
void scrollVerticalRemovedItem(int index) {
	int itemHeight = getItemHeight();
	int headerHeight = getHeaderHeight();
	int destY;
	Rectangle clientArea = getClientArea();		

	destY = Math.max(headerHeight, headerHeight + (index - getTopIndex()) * itemHeight);
	scroll(
		0, destY, 								// destination x, y
		0, destY + itemHeight,					// source x, y
		clientArea.width, clientArea.height, true);
}
/**
 * Selects the items at the given zero-relative indices in the receiver.
 * If the item at the given zero-relative index in the receiver 
 * is not selected, it is selected.  If the item at the index
 * was selected, it remains selected. Indices that are out
 * of range and duplicate indices are ignored.
 *
 * @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>
 */
public void select(int indices[]) {
	checkWidget();
	SelectableItem item = null;
	int selectionCount;

	if (indices == null) {
		error(SWT.ERROR_NULL_ARGUMENT);
	}
	selectionCount = indices.length;
	if (isMultiSelect() == false && selectionCount > 1) {
		selectionCount = 1;
		deselectAllExcept(getVisibleItem(indices[0]));
	}
	for (int i = selectionCount - 1; i >= 0; --i) {
		item = getVisibleItem(indices[i]);
		if (item != null) {
			select(item);
		}
	}
	if (item != null) {
		setLastSelection(item, false);
	}
}
/**
 * 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();
	SelectableItem item = getVisibleItem(index);
	
	if (isMultiSelect() == false) {
		deselectAllExcept(getVisibleItem(index));
	}
	if (item != null) {
		select(item);
		setLastSelection(item, false);
	}
}
/**
 * Selects the items at the given zero-relative indices in the receiver.
 * If the item at the index was already selected, it remains
 * selected. The range of the indices is inclusive. Indices that are
 * out of range are ignored.
 *
 * @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>
 */
public void select(int start, int end) {
	checkWidget();
	SelectableItem item = null;
	
	if (isMultiSelect() == false) {
		if (start < 0 && end >= 0) {
			start = 0;
		}
		end = start;
		deselectAllExcept(getVisibleItem(end));
	}
	// select in the same order as all the other selection and deslection methods.
	// Otherwise setLastSelection repeatedly changes the lastSelectedItem for repeated 
	// selections of the items, causing flash.
	for (int i = end; i >= start; i--) {
		item = getVisibleItem(i);
		if (item != null) {
			select(item);
		}
	}
	if (item != null) {
		setLastSelection(item, false);
	}
}
/**
 * Selects all 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 void selectAll() {
	checkWidget();
	Enumeration items = getItemVector().elements();
	TableItem item = null;

	if (isMultiSelect() == false) {
		return;
	}
	while (items.hasMoreElements() == true) {
		item = (TableItem) items.nextElement();
		select(item);
	}
	if (item != null) {
		setLastSelection(item, false);
	}
}
/**
 * Set the y position of 'column'.
 * @param column - the TableColumn that should be set to 
 *	a new y position.
 */
void setColumnPosition(TableColumn column) {
	Rectangle bounds = column.getBounds();

	bounds.y = getHeaderHeight() - getTopIndex() * getItemHeight();
	column.setBounds(bounds);	
}
/**
 * Change the cursor of the receiver.
 * @param isColumnResizeCursor - indicates whether the column 
 *	resize cursor or the regular cursor should be set.
 */
void setColumnResizeCursor(boolean isColumnResizeCursor) {
	if (isColumnResizeCursor != this.isColumnResizeCursor) {
		this.isColumnResizeCursor = isColumnResizeCursor;
		if (isColumnResizeCursor == true) {
			setCursor(getColumnResizeCursor());
		}
		else {
			setCursor(null);
		}
	}
}
/**
 * Set the current position of the resized column to 'xPosition'.
 * @param xPosition - the current position of the resized column
 */
void setColumnResizeX(int xPosition) {
	columnResizeX = xPosition;
}
/**
 * Set the width of the receiver's contents to 'newWidth'.
 * Content width is used to calculate the horizontal scrollbar.
 */
void setContentWidth(int newWidth) {
	TableColumn fillColumn = getFillColumn();
	Rectangle fillColumnBounds;
	int widthDiff = newWidth - getContentWidth();

	super.setContentWidth(newWidth);
	if (fillColumn != null) {
		fillColumnBounds = fillColumn.getBounds();
		fillColumnBounds.x += widthDiff;
		fillColumnBounds.width = Math.max(0, getClientArea().width - newWidth);
		fillColumn.setBounds(fillColumnBounds);
	}
}
/**
 * Set the width of the first column to fit 'item' if it is longer than 
 * the current column width.
 * Do nothing if the user has already set a width.
 */
void setFirstColumnWidth(TableItem item) {
	int newWidth;
	TableColumn column;

	if (internalGetColumnCount() > 0) {
		column = internalGetColumn(TableColumn.FIRST);		
		if (column.isDefaultWidth() == true) {
			newWidth = Math.max(column.getWidth(), item.getPreferredWidth(TableColumn.FIRST));
			column.setWidth(newWidth);
			column.setDefaultWidth(true);					// reset to true so that we know when the user has set 
															// the width instead of us setting a default width.
		}
	}
}
public void setFont(Font font) {
	checkWidget();
	int itemCount = getItemCount();

	if (font == null || font.equals(getFont()) == true) {
		return;
	}
	setRedraw(false);						// disable redraw because itemChanged() triggers undesired redraw	
	resetItemData();	
	super.setFont(font);
	
	GC gc = new GC(this);
	Point extent = gc.stringExtent(DOT_STRING);
	dotsWidth = extent.x;
	fontHeight = extent.y;
	gc.dispose();
	
	for (int i = 0; i < itemCount; i++) {
		itemChanged(getItem(i), 0, getClientArea().width);
	}
	setRedraw(true);						// re-enable redraw
	getHeader().setFont(font);
}
/**
 * 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 visible 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();
	if (headerVisible != getHeaderVisible()) {
		getHeader().setLocation(0, 0);
		getHeader().setVisible(headerVisible);
		// Windows resets scrolling so do we
		setTopIndex(0, true);
		moveColumnsVertical();
		resizeVerticalScrollbar();
		redraw();
	}
}
/**
 * Set the vector that stores the items of the receiver 
 * to 'newVector'.
 * @param newVector - Vector to use for storing the items of 
 *	the receiver.
 */
void setItemVector(Vector newVector) {
	items = newVector;
}
/**
 * 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 visible 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 drawGridLines) {
	checkWidget();
	if (this.drawGridLines != drawGridLines) {
		this.drawGridLines = drawGridLines;
		redraw();
	}
}
public void setRedraw(boolean redraw) {
	checkWidget();
	super.setRedraw(redraw);
	getHeader().setRedraw(redraw);
}
/**
 * Set the column that is being resized to 'column'. 
 * @param column - the TableColumn that is being resized. 
 * 	A null value indicates that no column resize operation is 
 *	in progress.
 */
void setResizeColumn(TableColumn column) {
	resizeColumn = column;
}
/**
 * Selects the items at the given zero-relative indices in the receiver. 
 * The current selected is first cleared, then the new items are selected.
 *
 * @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();
	Vector keepSelected;
	
	if (indices == null)  {
		error(SWT.ERROR_NULL_ARGUMENT);
	}	
	keepSelected = new Vector(indices.length);
	for (int i = 0; i < indices.length; i++) {
		SelectableItem item = getVisibleItem(indices[i]);
		if (item != null) {
			keepSelected.addElement(item);
		}
	}
	deselectAllExcept(keepSelected);
	select(indices);
}
/**
 * Sets the receiver's selection to be the given array of items.
 * The current selected is first cleared, then the new items are
 * selected.
 *
 * @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 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#deselectAll()
 * @see Table#select(int)
 */
public void setSelection(TableItem selectionItems[]) {
	checkWidget();
	if (selectionItems == null)  {
		error(SWT.ERROR_NULL_ARGUMENT);
	}	
	setSelectableSelection(selectionItems);
}
/**
 * Selects the item at the given zero-relative index in the receiver. 
 * The current selected 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();
	deselectAllExcept(getVisibleItem(index));
	select(index);
}
/**
 * Selects the items at the given zero-relative indices in the receiver. 
 * The current selected if first cleared, then the new items are selected.
 *
 * @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();
	Vector keepSelected = new Vector(end - start + 1);
	
	for (int i = start; i <= end; i++) {
		SelectableItem item = getVisibleItem(i);
		if (item != null) {
			keepSelected.addElement(item);
		}
	}	
	deselectAllExcept(keepSelected);
	select(start, end);
}
/**
 * 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 index 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 index) {
	checkWidget();
	int itemCount = getItemCount();
	int itemCountWhole = getItemCountWhole();
	
	if (index < 0 || itemCount == 0) {
		return;
	}
	if (index >= itemCount) {
		index = itemCount - itemCountWhole;
	}
	super.setTopIndex(index, true);
}
/**
 * Set the index of the first visible item in the receiver's client 
 * area to 'index'.
 * @param index - 0-based index of the first visible item in the 
 *	receiver's client area.
 * @param adjustScrollbar - true=set the position of the vertical 
 *	scroll bar to the new top index. 
 *	false=don't adjust the vertical scroll bar
 */
void setTopIndexNoScroll(int index, boolean adjustScrollbar) {
	super.setTopIndexNoScroll(index, adjustScrollbar);
	moveColumnsVertical();
}
/**
 * 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);
	showSelectableItem(item);
}
/**
 * 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 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 Table#showItem(TableItem)
 */
public void showSelection() {
	checkWidget();
	super.showSelection();
}
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;
		   		}
	    	}
	    }
	}
}
/**
 * Start a column resize operation.
 * @param event - the mouse event that occured over the header 
 * 	widget
 */
void startColumnResize(Event event) {
	Vector columns = internalGetColumnVector();
	TableColumn hitColumn = getColumnAtX(event.x);
	Rectangle hitColumnBounds;
	int hitIndex = hitColumn.getIndex();

	if (hitColumn == getFillColumn()) {										// clicked on the fill column?
		hitColumn = (TableColumn) columns.lastElement();					// resize the last real column
	}
	else 
	if ((event.x - hitColumn.getBounds().x <= COLUMN_RESIZE_OFFSET) && 		// check if left side of a column was clicked
		(hitIndex > 0)) {													
		hitColumn = (TableColumn) columns.elementAt(hitIndex - 1);			// resize the preceding column
	}
	hitColumnBounds = hitColumn.getBounds();
	setColumnResizeX(hitColumnBounds.x + hitColumnBounds.width);
	setResizeColumn(hitColumn);
}
/**
 * Return 'text' after it has been checked to be no longer than 'maxWidth' 
 * when drawn on 'gc'.
 * If it is too long it will be truncated up to the last character.
 * @param text - the String that should be checked for length
 * @param maxWidth - maximum width of 'text'
 * @param gc - GC to use for String measurement
 */
String trimItemText(String text, int maxWidth, GC gc) {
	int textWidth;
	int dotsWidth;

	if (text != null && text.length() > 1) {
		textWidth = gc.stringExtent(text).x;
		if (textWidth > maxWidth) {
			dotsWidth = getDotsWidth(gc);
			while (textWidth + dotsWidth > maxWidth && text.length() > 1) {
				text = text.substring(0, text.length() - 1);		// chop off one character at the end
				textWidth = gc.stringExtent(text).x;
			}
			text = text.concat(Table.DOT_STRING);
		}
	}
	return text;
}

}
