package org.eclipse.swt.widgets;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved
 */
 
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import java.util.Vector;

/**
 * Instances of this class represent a selectable user interface object
 * that represents an item in a table.
 * <dl>
 * <dt><b>Styles:</b></dt>
 * <dd>(none)</dd>
 * <dt><b>Events:</b></dt>
 * <dd>(none)</dd>
 * </dl>
 * <p>
 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
 * </p>
 */
public class TableItem extends SelectableItem {
	private static final int FIRST_COLUMN_IMAGE_INDENT = 2;	// Space in front of image - first column only
	private static final int FIRST_COLUMN_TEXT_INDENT = 4;	// Space in front of text - first column only	
	private static final int TEXT_INDENT_NO_IMAGE = 2;		// Space in front of item text when no item in the column has an image - first column only
	private static final int TEXT_INDENT = 6;				// Space in front of item text - all other columns
	private static final int SELECTION_PADDING = 6;			// Space behind text in a selected item

	private Vector dataLabels = new Vector();				// Original text set by the user. Items that don't 
															// have a label are represented by a null slot
	private String[] trimmedLabels = new String[0];			// Text that is actually displayed, may be trimmed 
															// to fit the column
	private Vector images = new Vector();					// Item images. Items that don't have an image 
															// are represented by a null slot
	private Point selectionExtent;							// Size of the rectangle drawn to indicate a 
															// selected item.
	private int imageIndent = 0;							// the factor by which the item image and check box, if any, 
															// are indented. The multiplier is the image width.
	private int index;										// index of the item in the parent widget

/**
 * Constructs a new instance of this class given its parent
 * (which must be a <code>Table</code>) and a style value
 * describing its behavior and appearance. The item is added
 * to the end of the items maintained by its parent.
 * <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
 * for all SWT widget classes should include a comment which
 * describes the style constants which are applicable to the class.
 * </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
 * @see Widget#checkSubclass
 * @see Widget#getStyle
 */
public TableItem(Table parent, int style) {
	this(parent, style, checkNull(parent).getItemCount());
}

/**
 * Constructs a new instance of this class given its parent
 * (which must be a <code>Table</code>), a style value
 * describing its behavior and appearance, and the index
 * at which to place it in the items maintained by its parent.
 * <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
 * for all SWT widget classes should include a comment which
 * describes the style constants which are applicable to the class.
 * </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
 * @param index the index to store the receiver in its parent
 *
 * @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
 * @see Widget#checkSubclass
 * @see Widget#getStyle
 */
public TableItem(Table parent, int style, int index) {
	super(parent, style);
	parent.addItem(this, index);
}

/**
 * Calculate the size of the rectangle drawn to indicate a selected 
 * item. This is also used to draw the selection focus rectangle. 
 * The selection extent is calculated for the first column only (the 
 * only column the selection is drawn in).
 */
void calculateSelectionExtent() {
	Table parent = getParent();
	TableColumn column = parent.internalGetColumn(TableColumn.FIRST);
	GC gc = new GC(parent);	
	String trimmedText = getText(gc, column);
	int gridLineWidth = parent.getGridLineWidth();
	
	if (trimmedText != null) {
		selectionExtent = new Point(gc.stringExtent(trimmedText).x, parent.getItemHeight());
		selectionExtent.x += getTextIndent(TableColumn.FIRST) + SELECTION_PADDING;
		selectionExtent.x = Math.min(
			selectionExtent.x, column.getWidth() - getImageStopX(column.getIndex()) - gridLineWidth);
		if (parent.getLinesVisible() == true) {
			selectionExtent.y -= gridLineWidth;
		}
	}
	gc.dispose();
}
/**
 * Throw an SWT.ERROR_NULL_ARGUMENT exception if 'table' is null.
 * Otherwise return 'table'
 */
static Table checkNull(Table table) {
	if (table == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	return table;
}
protected void checkSubclass () {
	if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
}
public void dispose() {
	if (isDisposed()) return;
	Table parent = getParent();
	parent.removeItem(this);
	super.dispose();
}
void doDispose() {
	dataLabels = null;
	trimmedLabels = null;
	images = null;
	selectionExtent = null;
	super.doDispose();
}

/**
 * Draw the image of the receiver for column 'index' at
 * 'destinationPosition' using 'gc'.
 * Stretch/shrink the image to the fixed image size of the receiver's 
 * parent.
 * @param gc - GC to draw on. 
 * @param destinationPosition - position on the GC to draw at.
 * @param index - index of the image to draw
 * @return Answer the position where drawing stopped.
 */
Point drawImage(GC gc, Point destinationPosition, int index) {
	Table parent = getParent();
	Image image = getImage(index);
	Rectangle sourceImageBounds;
	Point destinationImageExtent = parent.getImageExtent();
	
	if (image != null) {
		sourceImageBounds = image.getBounds();
		// full row select would obscure transparent images in all but the first column
		// so always clear the image area in this case. Fixes 1FYNITC
		if ((parent.getStyle() & SWT.FULL_SELECTION) != 0 && index != TableColumn.FIRST) {
			gc.fillRectangle(
				destinationPosition.x, destinationPosition.y,			
				destinationImageExtent.x, destinationImageExtent.y);
		}
		gc.drawImage(
			image, 0, 0, 													// source x, y
			sourceImageBounds.width, sourceImageBounds.height, 				// source width, height
			destinationPosition.x, destinationPosition.y,					// destination x, y
			destinationImageExtent.x, destinationImageExtent.y);			// destination width, height
	}
	if (((index == TableColumn.FIRST &&										// always add the image width for the first column 
 	 	  parent.hasFirstColumnImage() == true) ||							// if any item in the first column has an image
		 (index != TableColumn.FIRST && 									// add the image width if it's not the first column
		  image != null)) &&										 		// only when the item actually has an image
		destinationImageExtent != null) {									
		destinationPosition.x += destinationImageExtent.x;
	}
	return destinationPosition;
}
/**
 * Draw the label of the receiver for column 'index' at 'position'
 * using 'gc'. 
 * The background color is set to the selection background color if 
 * the item is selected and the text is drawn for the first column.
 * @param gc - GC to draw on. 
 * @param position - position on the GC to draw at.
 * @param index - specifies which subitem text to draw
 */
void drawText(String label, GC gc, Point position, int index) {
	Table parent = getParent();
	boolean drawSelection;
	int textOffset;
	int textHeight;
		
	if (label != null) {
		drawSelection = (index == TableColumn.FIRST || (parent.getStyle() & SWT.FULL_SELECTION) != 0);
		if (isSelected() == true && drawSelection == true) {
			gc.setBackground(getSelectionBackgroundColor());
			gc.setForeground(getSelectionForegroundColor());
		}
		textHeight = gc.stringExtent(label).y;
		textOffset = (parent.getItemHeight() - textHeight) / 2;			// vertically center the text
		gc.drawString(label, position.x, position.y + textOffset);
		if (isSelected() == true && drawSelection == true) {
			gc.setBackground(parent.getBackground());
			gc.setForeground(parent.getForeground());
		}
	}
}

/**
 * Returns a rectangle describing the receiver's size and location
 * relative to its parent at a column in the table.
 *
 * @param index the index that specifies the column
 * @return the receiver's bounding column rectangle
 *
 * @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 Rectangle getBounds(int index) {
	checkWidget();
	Rectangle itemBounds;
	Rectangle columnBounds;
	Rectangle checkboxBounds;
	Table parent = getParent();
	TableColumn column;
	int itemIndex = parent.indexOf(this);
	int itemHeight = parent.getItemHeight();
	int gridLineWidth = parent.getGridLineWidth();
	int itemYPos;
	
	if (itemIndex == -1 || index < 0 || index >= parent.internalGetColumnCount()) {
		itemBounds = new Rectangle(0, 0, 0, 0);
	}
	else {
		column = parent.internalGetColumn(index);
		columnBounds = column.getBounds();
		itemYPos = columnBounds.y + itemHeight * itemIndex;
		itemBounds = new Rectangle(
			columnBounds.x, itemYPos, 
			columnBounds.width - gridLineWidth, itemHeight - gridLineWidth);
		if (index == TableColumn.FIRST) {
			if (isCheckable() == true) {
				checkboxBounds = getCheckboxBounds();
				itemBounds.x += checkboxBounds.x + checkboxBounds.width + CHECKBOX_PADDING;	// add checkbox start, width and space behind checkbox
				itemBounds.width -= itemBounds.x;
			}
			else {
				itemBounds.x += getImageIndentPixel();
			}
		}
	}
	return itemBounds;
}
/**
 * Returns <code>true</code> if the receiver is checked,
 * and false otherwise.  When the parent does not have
 * the <code>CHECK style, return false.
 *
 * @return the checked 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 getChecked() {
	checkWidget();
	return super.getChecked();
}
/**
 * Answer the x position of the item check box
 */
int getCheckboxXPosition() {
	return getImageIndentPixel();
}
/**
 * Answer the item labels set by the user.
 * These may not be the same as those drawn on the screen. The latter 
 * may be trimmed to fit the column. Items that don't have a label are 
 * represented by a null slot in the vector.
 * @return Vector - the item labels set by the user.
 */
Vector getDataLabels() {
	return dataLabels;
}
public Display getDisplay() {
	return super.getDisplay();
}
/**
 * Return the position at which the string starts that is used 
 * to indicate a truncated item text.
 * @param columnIndex - index of the column for which the position of 
 *	the truncation replacement should be calculated
 * @param columnWidth - width of the column for which the position of 
 *	the truncation replacement should be calculated
 * @return -1 when the item text is not truncated
 */
int getDotStartX(int columnIndex, int columnWidth) {
	GC gc;
	Table parent = getParent();
	String label = getText(columnIndex);
	int dotStartX = -1;
	int maxWidth;

	if (label != null) {
		gc = new GC(parent);
		maxWidth = getMaxTextWidth(columnIndex, columnWidth);
		label = parent.trimItemText(label, maxWidth, gc);
		if (label.endsWith(Table.DOT_STRING) == true) {
			dotStartX = gc.stringExtent(label).x - parent.getDotsWidth(gc);
			// add indents, margins and image width
			dotStartX += getImageStopX(columnIndex);
			dotStartX += getTextIndent(columnIndex);
		}
		gc.dispose();		
	}
	return dotStartX;
}
/**
 * Returns <code>true</code> if the receiver is grayed,
 * and false otherwise. When the parent does not have
 * the <code>CHECK style, return false.
 *
 * @return the grayed 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 getGrayed() {
	checkWidget();
	return super.getGrayed();
}
public Image getImage() {
	checkWidget();
	return getImage(0);
}
/**
 * Returns the item image of the column identified by 'columnIndex' or 
 * null if no image has been set for that column.
 * 
 * @param columnIndex - the column whose image should be returned
 * @return the item image
 */
public Image getImage(int columnIndex) {
	checkWidget();
	Image image = null;
	Vector images = getImages();
	int itemIndex = getParent().indexOf(this);
	
	if (itemIndex != -1 && columnIndex >= 0 && columnIndex < images.size()) {
		image = (Image) images.elementAt(columnIndex);
	}
	return image;
}
/**
 * Returns a rectangle describing the size and location
 * relative to its parent of an image at a column in the
 * table.
 *
 * @param index the index that specifies the column
 * @return the receiver's bounding image rectangle
 *
 * @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 Rectangle getImageBounds(int index) {
	checkWidget();
	Table parent = getParent();
	int itemIndex = parent.indexOf (this);
	int imageWidth = 0;
	Point imageExtent = parent.getImageExtent();
	Rectangle checkboxBounds;
	Rectangle imageBounds = getBounds(index);
	
	if (itemIndex == -1) {
		imageBounds = new Rectangle(0, 0, 0, 0);
	}
	else
	if (imageExtent != null) {
		if (index == TableColumn.FIRST || getImage(index) != null) {
			imageWidth = imageExtent.x;
		}
	}
	imageBounds.width = imageWidth;
	return imageBounds;
}
/**
 * Gets the image indent.
 *
 * @return the indent
 *
 * @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 getImageIndent() {
	checkWidget();
	int index = getParent().indexOf(this);
	
	if (index == -1) {
		return 0;
	}
	return imageIndent;
}
/**
 * Answer the number of pixels the image in the first column is 
 * indented. Calculation starts at the column start and counts 
 * all pixels except the check box.
 */
int getImageIndentPixel() {
	int indentPixel = FIRST_COLUMN_IMAGE_INDENT;
	Point imageExtent = getParent().getImageExtent();
	
	if (imageExtent != null) {
		indentPixel += imageExtent.x * getImageIndent();
	}
	return indentPixel;
}
/**
 * Answer the item images set by the user. Items that don't have an 
 * image are represented by a null slot in the vector.
 */
Vector getImages() {
	return images;
}
/**
 * Calculate the x coordinate where the item image of column 
 * 'columnIndex' stops.
 * @param columnIndex - the column for which the stop position of the 
 *	image should be calculated.
 */
int getImageStopX(int columnIndex) {
	int imageStopX = 0;
	Table parent = getParent();
	Rectangle checkboxBounds;

	if (columnIndex == TableColumn.FIRST) {
		if (isCheckable() == true) {
			checkboxBounds = getCheckboxBounds();
			imageStopX += checkboxBounds.x + checkboxBounds.width + CHECKBOX_PADDING;
		}
		else {
			imageStopX = getImageIndentPixel();
		}
	}
	if (((columnIndex == TableColumn.FIRST &&				// always add the image width for the first column 
 	 	  parent.hasFirstColumnImage() == true) ||			// if any item in the first column has an image
		 (columnIndex != TableColumn.FIRST && 				// add the image width if it's not the first column
		  getImage(columnIndex) != null)) &&		 		// only when the item actually has an image
		parent.getImageExtent() != null) {									
		imageStopX += parent.getImageExtent().x;
	}
	return imageStopX;
}
/**
 * Return the index of the item in its parent widget.
 */
int getIndex() {
	return index;
}
/**
 * Return the item extent in the specified column
 * The extent includes the actual width of the item including checkbox, 
 * image and text.
 */
Point getItemExtent(TableColumn column) {
	Table parent = getParent();
	int columnIndex = column.getIndex();
	Point extent = new Point(getImageStopX(columnIndex), parent.getItemHeight() - parent.getGridLineWidth());
	GC gc = new GC(parent);	
	String trimmedText = getText(gc, column);

	if (trimmedText != null && trimmedText.length() > 0) {
		extent.x += gc.stringExtent(trimmedText).x + getTextIndent(columnIndex);
	}
	if (columnIndex == TableColumn.FIRST) {
		extent.x += SELECTION_PADDING;
	}
	gc.dispose();		
	return extent;
}
/**
 * Answer the maximum width in pixel of the text that fits in the 
 * column identified by 'columnIndex' without trimming the text.
 * @param columnIndex - the column for which the maximum text width
 *	should be calculated.
 * @param columnWidth - width of the column 'columnIndex'
 */
int getMaxTextWidth(int columnIndex, int columnWidth) {
	int itemWidth = getImageStopX(columnIndex) + getTextIndent(columnIndex) * 2;
	return columnWidth - itemWidth;
}
/**
 * Returns the receiver's parent, which must be a <code>Table</code>.
 *
 * @return the receiver's parent
 *
 * @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 Table getParent() {
	checkWidget();
	return (Table) super.getSelectableParent();
}
/**
 * Answer the width of the item required to display the complete contents.
 */
int getPreferredWidth(int index) {
	int size = getImageStopX(index);
	String text = getText(index);
	if (text != null) {
		size += getParent().getTextWidth(text) + getTextIndent(index) * 2 + 1;
	}
	return size;
}
/**
 * Return the size of the rectangle drawn to indicate a selected item.
 * This is also used to draw the selection focus rectangle and drop 
 * insert marker. 
 * Implements SelectableItem#getSelectionExtent
 */
Point getSelectionExtent() {
	Table parent = getParent();
	Point extent;
	
	if ((parent.getStyle() & SWT.FULL_SELECTION) == 0) {			// regular, first column, selection?
		if (selectionExtent == null) {
			calculateSelectionExtent();
		}
		extent = selectionExtent;
	}
	else {
		extent = parent.getFullSelectionExtent(this);
	}
	return extent;
}
/**
 * Return the x position of the selection rectangle
 * Implements SelectableItem#getSelectionX
 */
int getSelectionX() {
	return getImageStopX(TableColumn.FIRST) + getParent().getHorizontalOffset();
}
public String getText() {
	checkWidget();
	return getText(0);
}
/**
 * Returns the item tezt of the column identified by 'columnIndex',
 * or null if no text has been set for that column.
 * 
 * @param columnIndex - the column whose text should be returned
 *	@return the item text or null if no text has been set for that column.
 */
public String getText(int columnIndex) {
	checkWidget();
	int itemIndex = getParent().indexOf(this);
	Vector labels = getDataLabels();
	String label = null;
	
	if (itemIndex == -1) {
		error(SWT.ERROR_CANNOT_GET_TEXT);
	}	
	if (columnIndex >= 0 && columnIndex < labels.size()) {
		label = (String) labels.elementAt(columnIndex);
	}
	if (label == null) {
		label = "";			// label vector is initialized with null instead of empty Strings
	}
	return label;
}
/**
 * Answer the text that is going to be drawn in 'column'. This 
 * text may be a trimmed copy of the original text set by the 
 * user if it doesn't fit into the column. In that case the last 
 * characters are replaced with Table.DOT_STRING.
 * A cached copy of the trimmed text is returned if available.
 * @param gc - GC to use for measuring the text extent
 * @param column - TableColumn for which the text should be returned
 */
String getText(GC gc, TableColumn column) {
	int columnIndex = column.getIndex();
	String label = getTrimmedText(columnIndex);
	int maxWidth;

	if (label == null) {
		maxWidth = getMaxTextWidth(columnIndex, column.getWidth());
		label = getParent().trimItemText(getText(columnIndex), maxWidth, gc);
	}
	return label;
}
/**
 * Answer the indent of the text in column 'columnIndex' in pixel.
 * This indent is used in front of and behind the item text.
 * @param columnIndex - specifies the column for which the indent 
 *	should be calculated.
 */
int getTextIndent(int columnIndex) {
	int textIndent;

	if (columnIndex == TableColumn.FIRST) {
		if (getParent().hasFirstColumnImage() == false) {
			textIndent = TEXT_INDENT_NO_IMAGE;
		}
		else {
			textIndent = FIRST_COLUMN_TEXT_INDENT;
		}
	}
	else {
		textIndent = TEXT_INDENT;
	}
	return textIndent;
}
/**
 * Answer the cached trimmed text for column 'columnIndex'. 
 * Answer null if it hasn't been calculated yet.
 * @param columnIndex - specifies the column for which the 
 *	trimmed text should be answered.
 */
String getTrimmedText(int columnIndex) {
	String label = null;
	String labels[] = getTrimmedTexts();

	if (columnIndex < labels.length) {
		label = labels[columnIndex];
	}
	return label;
}
/**
 * Answer an array of cached trimmed labels.
 */
String [] getTrimmedTexts() {
	return trimmedLabels;
}
/**
 * Ensure that the image and label vectors have at least 
 * 'newSize' number of elements.
 */
void growVectors(int newSize) {
	Vector images = getImages();
	Vector labels = getDataLabels();

	if (newSize > images.size()){
		images.setSize(newSize);
	}
	if (newSize > labels.size()){
		labels.setSize(newSize);
	}
}
/**
 * Insert 'column' into the receiver.
 */
void insertColumn(TableColumn column) {	
	Vector data = getDataLabels();
	Vector images = getImages();
	String stringData[];
	Image imageData[];
	int index = column.getIndex();

	if (index < data.size()) {
		data.insertElementAt(null, index);
	}
	else {
		data.addElement(null);
	}
	stringData = new String[data.size()];
	data.copyInto(stringData);
	setText(stringData);

	if (index < images.size()) {	
		images.insertElementAt(null, index);
	}
	else {
		images.addElement(null);
	}
	imageData = new Image[images.size()];
	images.copyInto(imageData);
	setImage(imageData);
}
/**
 * Sets the image at an index.
 *
 * @param image the new image (or null)
 *
 * @exception SWTError(ERROR_THREAD_INVALID_ACCESS)
 *	when called from the wrong thread
 * @exception SWTError(ERROR_WIDGET_DISPOSED)
 *	when the widget has been disposed
 */
void internalSetImage(int columnIndex, Image image) {
	Vector images = getImages();
	boolean imageWasNull = false;
	Table parent = getParent();		
	
	if (columnIndex >= 0 && 
		columnIndex < parent.internalGetColumnCount()) {
		if (columnIndex >= images.size()) {
			growVectors(columnIndex + 1);
		}
		if (((Image) images.elementAt(columnIndex)) == null && image != null) {
			imageWasNull = true;
		}
		if (image != null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
		images.setElementAt(image, columnIndex);
		reset(columnIndex);						// new image may cause text to no longer fit in the column
		notifyImageChanged(columnIndex, imageWasNull);
	}
}
/**
* Sets the widget text.
*
* The widget text for an item is the label of the
* item or the label of the text specified by a column
* number.
*
* @param index the column number
* @param text the new text
*
*/
void internalSetText(int columnIndex, String string) {
	Vector labels = getDataLabels();
	Table parent = getParent();
	String oldText;
	
	if (columnIndex >= 0 &&
		columnIndex < parent.internalGetColumnCount()) {
		if (columnIndex >= labels.size()) {
			growVectors(columnIndex + 1);
		}
		oldText = (String) labels.elementAt(columnIndex);
		if (string.equals(oldText) == false) {
			labels.setElementAt(string, columnIndex);
			reset(columnIndex);
			notifyTextChanged(columnIndex, oldText == null);
		}
	}
}
/**
 * Answer whether the click at 'xPosition' on the receiver is a 
 * selection click.
 * A selection click occurred when the click was behind the image
 * and before the end of the item text.
 * @return 
 *	true - 'xPosition' is a selection click.
 *	false - otherwise
 */
boolean isSelectionHit(int xPosition) {
	int itemStopX = getImageStopX(TableColumn.FIRST);
	Point selectionExtent = getSelectionExtent();

	if (selectionExtent != null) {
		itemStopX += selectionExtent.x;
	}
	return (xPosition > getCheckboxBounds().x + getCheckboxBounds().width) && (xPosition <= itemStopX);
}
/** 
 * The image for the column identified by 'columnIndex' has changed.
 * Notify the parent widget and supply redraw coordinates, if possible.
 * @param columnIndex - index of the column that has a new image.
 */
void notifyImageChanged(int columnIndex, boolean imageWasNull) {	
	Table parent = getParent();
	Rectangle changedColumnBounds;
	int redrawStartX = 0;
	int redrawWidth = 0;
	int columnCount = parent.internalGetColumnCount();	

	if (columnIndex >= 0 && columnIndex < columnCount && parent.getVisibleRedrawY(this) != -1) {
		changedColumnBounds = parent.internalGetColumn(columnIndex).getBounds();
		redrawStartX = Math.max(0, getImageBounds(columnIndex).x);
		if (parent.getImageExtent() != null && imageWasNull == false) {
			redrawWidth = getImageStopX(columnIndex);
		}
		else {
			redrawWidth = changedColumnBounds.width;
		}
		redrawWidth += changedColumnBounds.x - redrawStartX;
	}
	parent.itemChanged(this, redrawStartX, redrawWidth);
}

/**
 * The label for the column identified by 'columnIndex' has changed.
 * Notify the parent widget and supply redraw coordinates, if possible.
 * @param columnIndex - index of the column that has a new label.
 */
void notifyTextChanged(int columnIndex, boolean textWasNull) {	
	Table parent = getParent();
	String text;
	Rectangle columnBounds;
	int redrawStartX = 0;
	int redrawWidth = 0;
	int columnCount = parent.internalGetColumnCount();

	if (columnIndex >= 0 && columnIndex < columnCount && parent.getVisibleRedrawY(this) != -1) {
		text = (String) getDataLabels().elementAt(columnIndex);
		columnBounds = parent.internalGetColumn(columnIndex).getBounds();
		redrawStartX = columnBounds.x;
		if (getImage(columnIndex) != null) {
			redrawStartX += getImageStopX(columnIndex);
		}
		redrawStartX = Math.max(0, redrawStartX);
		// don't redraw if text changed from null to empty string
		if (textWasNull == false || text.length() > 0) {
			redrawWidth = columnBounds.x + columnBounds.width - redrawStartX;
		}
	}
	parent.itemChanged(this, redrawStartX, redrawWidth);
}
/**
 * Draw the receiver at 'paintPosition' in the column identified by 
 * 'columnIndex' using 'gc'.
 * @param gc - GC to use for drawing
 * @param paintPosition - position where the receiver should be drawing.
 * @param column - the column to draw in
 */
void paint(GC gc, Point paintPosition, TableColumn column) {
	int columnIndex = column.getIndex();
	String label = getText(gc, column);
	String oldLabel = getTrimmedText(columnIndex);

	if (label != null && label.equals(oldLabel) == false) {
		setTrimmedText(label, columnIndex);
		selectionExtent = null;		// force a recalculation next time the selection extent is needed
	}
	if (columnIndex == TableColumn.FIRST) {
		paintPosition.x += getImageIndentPixel();
		if (isCheckable() == true) {
			paintPosition = drawCheckbox(gc, paintPosition);
		}		
	}
	paintPosition = drawImage(gc, paintPosition, columnIndex);
	paintPosition.x += getTextIndent(columnIndex);
	drawText(label, gc, paintPosition, columnIndex);
}
/**
 * Remove 'column' from the receiver.
 */
void removeColumn(TableColumn column) {
	Vector data = getDataLabels();
	Vector images = getImages();
	String stringData[];
	Image imageData[];
	int index = column.getIndex();

	if (index < data.size()) {
		data.removeElementAt(index);
		stringData = new String[data.size()];
		data.copyInto(stringData);
		setText(stringData);
	}
	if (index < images.size()) {
		images.removeElementAt(index);
		imageData = new Image[images.size()];
		images.copyInto(imageData);
		setImage(imageData);
	}
}
/**
 * Reset the cached trimmed label for the sub item identified by 
 * 'index'.
 * @param index - index of the label that should be reset.
 */
void reset(int index) {
	String trimmedLabels[] = getTrimmedTexts();

	if (index >= 0 && index < trimmedLabels.length) {
		trimmedLabels[index] = null;
	}
	if (index == TableColumn.FIRST) {
		selectionExtent = null;
	}
}
/**
 * Sets the image for multiple columns in the Table. 
 * 
 * @param images the array of new images
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the array of images is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if one of the images 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 setImage(Image [] images) {
	checkWidget();
	if (images == null) {
		error(SWT.ERROR_NULL_ARGUMENT);
	}
	if (getParent().indexOf(this) == -1) {	
		return;
	}	
	for (int i = 0; i < images.length; i++) {
		internalSetImage(i, images[i]);
	}
}
/**
 * Sets the receiver's image at a column.
 *
 * @param index the column index
 * @param image the new image
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the image 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 setImage(int index, Image image) {
	checkWidget();	
	if (getParent().indexOf(this) != -1) {
		internalSetImage(index, image);
	}
}
public void setImage(Image image) {
	checkWidget();
	setImage(0, image);
}
/**
 * Sets the image indent.
 *
 * @param indent the new indent
 *
 * </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 setImageIndent(int indent) {
	checkWidget();
	Table parent = getParent();
	TableColumn column;
	int index = parent.indexOf(this);

	if (index != -1 && indent >= 0 && indent != imageIndent) {
		imageIndent = indent;
		column = parent.internalGetColumn(TableColumn.FIRST);
		parent.redraw(
			0, parent.getRedrawY(this), 
			column.getWidth(), parent.getItemHeight(), false);
	}
}
/**
 * Sets the text for multiple columns in the table. 
 * 
 * @param strings the array of new strings
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the text 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 setText(String [] strings) {
	checkWidget();
	if (strings == null) {
		error(SWT.ERROR_NULL_ARGUMENT);
	}
	if (getParent().indexOf(this) == -1) {	
		return;
	}
	for (int i = 0; i < strings.length; i++) {
		String string = strings[i];
		if (string != null) {
			internalSetText(i, string);
		}
	}
}
/**
 * Sets the receiver's text at a column
 *
 * @param index the column index
 * @param string the new text
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the text 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 setText (int index, String string) {
	checkWidget();
	if (string == null) {
		error(SWT.ERROR_NULL_ARGUMENT);
	}
	if (getParent().indexOf(this) != -1) {
		internalSetText(index, string);
	}
}
public void setText(String text) {
	checkWidget();
	if (text == null) {
		error(SWT.ERROR_NULL_ARGUMENT);
	}
	setText(0, text);
}
/**
 * Set the trimmed text of column 'columnIndex' to label. The trimmed 
 * text is the one that is displayed in a column. It may be shorter than
 * the text originally set by the user via setText(...) to fit the 
 * column.
 * @param label - the text label of column 'columnIndex'. May be trimmed
 *	to fit the column.
 * @param columnIndex - specifies the column whose text label should be 
 *	set.
 */
void setTrimmedText(String label, int columnIndex) {
	String labels[] = getTrimmedTexts();

	if (columnIndex < labels.length) {
		labels[columnIndex] = label;
	}
}
/**
 * Sets the checked state of the receiver.
 *
 * @param checked the new checked 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 setChecked(boolean checked) {
	checkWidget();
	super.setChecked(checked);
}
/**
 * Sets the grayed state of the receiver.
 *
 * @param checked the new grayed 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 setGrayed (boolean grayed) {
	checkWidget();
	super.setGrayed(grayed);
}
/**
 * Set the index of this item in its parent widget to 'newIndex'.
 */
void setIndex(int newIndex) {
	index = newIndex;
}

}