blob: 8c2056a3cd64765e46acf922052296ceb089ad51 [file] [log] [blame]
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;
}
}