/******************************************************************************* * Copyright (c) 2002, 2010 Innoopract Informationssysteme GmbH. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Innoopract Informationssysteme GmbH - initial API and implementation * EclipseSource - ongoing development ******************************************************************************/ package org.eclipse.swt.widgets; import org.eclipse.rwt.graphics.Graphics; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.graphics.*; import org.eclipse.swt.internal.widgets.*; /** * 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 Item { private final class TableItemAdapter implements ITableItemAdapter { public Color getUserBackground() { return background; } public Color getUserForeground() { return foreground; } public Font getUserFont() { return font; } public Color[] getCellBackgrounds() { int columnCount = Math.max( 1, getParent().getColumnCount() ); Color[] result = new Color[ columnCount ]; if( data != null ) { for( int i = 0; i < data.length; i++ ) { if( data[ i ] != null ) { result[ i ] = data[ i ].background; } } } return result; } public Color[] getCellForegrounds() { int columnCount = Math.max( 1, getParent().getColumnCount() ); Color[] result = new Color[ columnCount ]; if( data != null ) { for( int i = 0; i < data.length; i++ ) { if( data[ i ] != null ) { result[ i ] = data[ i ].foreground; } } } return result; } public Font[] getCellFonts() { int columnCount = Math.max( 1, getParent().getColumnCount() ); Font[] result = new Font[ columnCount ]; if( data != null ) { for( int i = 0; i < data.length; i++ ) { if( data[ i ] != null ) { result[ i ] = data[ i ].font; } } } return result; } public boolean isParentDisposed() { return TableItem.this.parent.isDisposed(); } } private static final class Data { String text = ""; Image image; Font font; Color background; Color foreground; } private final TableItemAdapter tableItemAdapter; final Table parent; boolean cached; int index; private Data[] data; private boolean checked; private boolean grayed; private Color background; private Color foreground; private Font font; /** * 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 * 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 * @see Widget#checkSubclass * @see Widget#getStyle */ public TableItem( final Table parent, final 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 * 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 * @param index the zero-relative index to store the receiver in its parent * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</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( final Table parent, final int style, final int index ) { this( parent, style, index, true ); } TableItem( final Table parent, final int style, final int index, final boolean create ) { super( parent, style ); this.parent = parent; this.index = index; tableItemAdapter = new TableItemAdapter(); if( create ) { this.parent.createItem( this, index ); } } public Object getAdapter( final Class adapter ) { Object result; if( adapter == IWidgetFontAdapter.class || adapter == IWidgetColorAdapter.class || adapter == ITableItemAdapter.class ) { result = tableItemAdapter; } else { result = super.getAdapter( adapter ); } return result; } /** * 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 parent; } /////////////////////////// // Methods to get/set texts public void setText( final String text ) { checkWidget(); setText( 0, text ); } /** * Sets the receiver's text at a column * * @param index the column index * @param text 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( final int index, final String text ) { checkWidget(); if( text == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } int count = Math.max( 1, parent.getColumnCount() ); if( index >= 0 && index < count ) { ensureData( index, count ); if( !text.equals( data[ index ].text ) ) { data[ index ].text = text; markCached(); if( parent.getColumnCount() == 0 ) { parent.updateScrollBars(); } parent.redraw(); } } } /** * 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> * * @since 1.2 */ public void setText( final String[] strings ) { checkWidget(); if( strings == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } for( int i = 0; i < strings.length; i++ ) { String string = strings[ i ]; if( string != null ) { setText( i, string ); } } } public String getText() { checkWidget(); return getText( 0 ); } /** * Returns the text stored at the given column index in the receiver, * or empty string if the text has not been set. * * @param index the column index * @return the text stored at the given column index 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 String getText( final int index ) { checkWidget(); if( !parent.checkData( this, parent.indexOf( this ) ) ) { error( SWT.ERROR_WIDGET_DISPOSED ); } String result = ""; if( data != null && index >= 0 && index < data.length && data[ index ] != null ) { result = data[ index ].text; } return result; } //////////////////////////// // Methods to get/set images public void setImage( final Image image ) { checkWidget(); setImage( 0, image ); } /** * 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( final int index, final Image image ) { checkWidget(); if( image != null && image.isDisposed() ) { error( SWT.ERROR_INVALID_ARGUMENT ); } int count = Math.max( 1, parent.getColumnCount() ); if( index >= 0 && index < count ) { ensureData( index, count ); if( !equals( data[ index].image, image ) ) { parent.updateColumnImageCount( index, data[ index ].image, image ); data[ index ].image = image; parent.updateItemImageSize( image ); markCached(); if( parent.getColumnCount() == 0 ) { parent.updateScrollBars(); } parent.redraw(); } } } /** * 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( final Image[] images ) { checkWidget(); if( images == null ) { error( SWT.ERROR_NULL_ARGUMENT ); } for( int i = 0; i < images.length; i++ ) { if( images[ i ] != null && images[ i ].isDisposed() ) { error( SWT.ERROR_INVALID_ARGUMENT ); } } for( int i = 0; i < images.length; i++ ) { setImage( i, images[ i ] ); } } public Image getImage() { checkWidget(); return getImage( 0 ); } /** * Returns the image stored at the given column index in the receiver, * or null if the image has not been set or if the column does not exist. * * @param index the column index * @return the image stored at the given column index 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 Image getImage( final int index ) { checkWidget(); if( !parent.checkData( this, parent.indexOf( this ) ) ) { error( SWT.ERROR_WIDGET_DISPOSED ); } return getImageInternal( index ); } Image getImageInternal( final int index ) { Image result = null; if( data != null && index >= 0 && index < data.length && data[ index ] != null ) { result = data[ index ].image; } return result; } //////////////////// // Colors and Fonts /** * Sets the receiver's background color to the color specified * by the argument, or to the default system color for the item * if the argument is null. * * @param color the new color (or null) * * @exception IllegalArgumentException <ul> * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> */ public void setBackground( final Color color ) { checkWidget(); if( color != null && color.isDisposed() ) { error( SWT.ERROR_INVALID_ARGUMENT ); } if( !equals( background, color ) ) { background = color; markCached(); parent.redraw(); } } /** * Returns the receiver's background color. * * @return the background color * * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> */ public Color getBackground() { checkWidget (); if( !parent.checkData( this, parent.indexOf( this ) ) ) { error( SWT.ERROR_WIDGET_DISPOSED ); } Color result; if( background == null ) { result = parent.getBackground(); } else { result = background; } return result; } /** * Sets the background color at the given column index in the receiver * to the color specified by the argument, or to the default system color for the item * if the argument is null. * * @param index the column index * @param color the new color (or null) * * @exception IllegalArgumentException <ul> * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> */ public void setBackground( final int index, final Color color ) { checkWidget(); if( color != null && color.isDisposed() ) { error( SWT.ERROR_INVALID_ARGUMENT ); } int count = Math.max( 1, parent.getColumnCount() ); if( index >= 0 && index < count ) { ensureData( index, count ); if( !equals( data[ index ].background, color ) ) { data[ index ].background = color; markCached(); parent.redraw(); } } } /** * Returns the background color at the given column index in the receiver. * * @param index the column index * @return the background color * * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> */ public Color getBackground( final int index ) { checkWidget(); if( !parent.checkData( this, parent.indexOf( this ) ) ) { error( SWT.ERROR_WIDGET_DISPOSED ); } Color result = getBackground(); if( data != null && index >= 0 && index < data.length && data[ index ] != null && data[ index ].background != null ) { result = data[ index ].background; } return result; } /** * Sets the receiver's foreground color to the color specified by the * argument, or to the default system color for the item if the argument is * null. * * @param color the new color (or null) * @exception IllegalArgumentException * <ul> * <li>ERROR_INVALID_ARGUMENT - if the argument has been * disposed</li> * </ul> * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setForeground( final Color color ) { checkWidget(); if( color != null && color.isDisposed() ) { error( SWT.ERROR_INVALID_ARGUMENT ); } if( !equals( foreground, color ) ) { foreground = color; markCached(); parent.redraw(); } } /** * Returns the foreground color that the receiver will use to draw. * * @return the receiver's foreground color * * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> */ public Color getForeground() { checkWidget(); if( !parent.checkData( this, parent.indexOf( this ) ) ) { error( SWT.ERROR_WIDGET_DISPOSED ); } Color result; if( foreground == null ) { result = parent.getForeground(); } else { result = foreground; } return result; } /** * Sets the foreground color at the given column index in the receiver * to the color specified by the argument, or to the default system color for the item * if the argument is null. * * @param index the column index * @param color the new color (or null) * * @exception IllegalArgumentException <ul> * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> */ public void setForeground( final int index, final Color color ) { checkWidget(); if( color != null && color.isDisposed() ) { error( SWT.ERROR_INVALID_ARGUMENT ); } int count = Math.max( 1, parent.getColumnCount() ); if( index >= 0 && index < count ) { ensureData( index, count ); if( !equals( data[ index ].foreground, color ) ) { data[ index ].foreground = color; markCached(); parent.redraw(); } } } /** * * Returns the foreground color at the given column index in the receiver. * * @param index the column index * @return the foreground color * * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> */ public Color getForeground( final int index ) { checkWidget(); if( !parent.checkData( this, parent.indexOf( this ) ) ) { error( SWT.ERROR_WIDGET_DISPOSED ); } Color result = getForeground(); if( data != null && index >= 0 && index < data.length && data[ index ] != null && data[ index ].foreground != null ) { result = data[ index ].foreground; } return result; } /** * Sets the font that the receiver will use to paint textual information * for this item to the font specified by the argument, or to the default font * for that kind of control if the argument is null. * * @param font the new font (or null) * * @exception IllegalArgumentException <ul> * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> */ public void setFont( final Font font ) { checkWidget(); if( font != null && font.isDisposed() ) { error( SWT.ERROR_INVALID_ARGUMENT ); } if( !equals( this.font, font ) ) { this.font = font; markCached(); if( parent.getColumnCount() == 0 ) { parent.updateScrollBars(); } parent.redraw(); } } /** * Returns the font that the receiver will use to paint textual information for this item. * * @return the receiver's font * * @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 Font getFont () { checkWidget (); if( !parent.checkData( this, parent.indexOf( this ) ) ) { error( SWT.ERROR_WIDGET_DISPOSED ); } Font result; if( font == null ) { result = parent.getFont(); } else { result = font; } return result; } /** * Sets the font that the receiver will use to paint textual information * for the specified cell in this item to the font specified by the * argument, or to the default font for that kind of control if the * argument is null. * * @param index the column index * @param font the new font (or null) * * @exception IllegalArgumentException <ul> * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> */ public void setFont( final int index, final Font font ) { checkWidget(); if( font != null && font.isDisposed() ) { error( SWT.ERROR_INVALID_ARGUMENT ); } int count = Math.max( 1, parent.getColumnCount() ); if( index >= 0 && index < count ) { ensureData( index, count ); if( !equals( font, data[ index ].font ) ) { data[ index ].font = font; markCached(); parent.redraw(); } } } /** * Returns the font that the receiver will use to paint textual information * for the specified cell in this item. * * @param index the column index * @return the receiver's font * * @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 Font getFont( final int index ) { checkWidget(); if( !parent.checkData( this, parent.indexOf( this ) ) ) { error( SWT.ERROR_WIDGET_DISPOSED ); } Font result = getFont(); if( data != null && index >= 0 && index < data.length && data[ index ] != null && data[ index ].font != null ) { result = data[ index ].font; } return result; } /////////////////// // Checked & Grayed /** * Sets the checked state of the checkbox for this item. This state change * only applies if the Table was created with the SWT.CHECK style. * * @param checked the new checked state of the checkbox * * @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( final boolean checked ) { checkWidget(); if( ( parent.style & SWT.CHECK ) != 0 ) { this.checked = checked; } } /** * Returns <code>true</code> if the receiver is checked, * and false otherwise. When the parent does not have * the <code>CHECK</code> style, return false. * * @return the checked state of the checkbox * * @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(); if( !parent.checkData( this, parent.indexOf( this ) ) ) { error( SWT.ERROR_WIDGET_DISPOSED ); } boolean result = false; if( ( parent.style & SWT.CHECK ) != 0 ) { result = checked; } return result; } /** * Sets the grayed state of the checkbox for this item. This state change * only applies if the Table was created with the SWT.CHECK style. * * @param grayed the new grayed state of the checkbox; * * @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( final boolean grayed ) { checkWidget(); if( ( parent.style & SWT.CHECK ) != 0 ) { this.grayed = grayed; } } /** * Returns <code>true</code> if the receiver is grayed, * and false otherwise. When the parent does not have * the <code>CHECK</code> style, return false. * * @return the grayed state of the checkbox * * @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(); if( !parent.checkData( this, parent.indexOf( this ) ) ) { error( SWT.ERROR_WIDGET_DISPOSED ); } boolean result = false; if( ( parent.style & SWT.CHECK ) != 0 ) { result = grayed; } return result; } ///////////////////// // Dimension methods /** * Returns a rectangle describing the receiver's size and location * relative to its parent. * * @return the receiver's bounding 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() { return getBounds( 0 ); } /** * 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( final int index ) { checkWidget(); if( !parent.checkData( this, parent.indexOf( this ) ) ) { error( SWT.ERROR_WIDGET_DISPOSED ); } Rectangle result; int columnCount = parent.getColumnCount(); if( columnCount > 0 && ( index < 0 || index >= columnCount ) ) { result = new Rectangle( 0, 0, 0, 0 ); } else { Rectangle textBounds = getTextBounds( index ); int left = getLeft( index ); int itemIndex = parent.indexOf( this ); int top = getTop( itemIndex ); int width = 0; if( index == 0 && columnCount == 0 ) { Rectangle imageBounds = getImageBounds( index ); int spacing = getSpacing( index ); int paddingWidth = parent.getCellPadding().width; width = imageBounds.width + spacing + textBounds.width + paddingWidth; } else if( index >= 0 && index < columnCount ) { width = parent.getColumn( index ).getWidth() - getCheckWidth( index ); } int height = getHeight( index ); result = new Rectangle( left, top, width, height ); } return result; } /** * Returns a rectangle describing the size and location * relative to its parent of an image at a column in the * table. An empty rectangle is returned if index exceeds * the index of the table's last column. * * @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( final int index ) { checkWidget(); if( !parent.checkData( this, parent.indexOf( this ) ) ) { error( SWT.ERROR_WIDGET_DISPOSED ); } int itemIndex = parent.indexOf( this ); Rectangle cellPadding = parent.getCellPadding(); int left = getLeft( index ) + cellPadding.x; int top = getTop( itemIndex ); int width = getImageWidth( index ); int height = getHeight( index ); return new Rectangle( left, top, width, height ); } /** * 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(); if( !parent.checkData( this, parent.indexOf( this ) ) ) { error( SWT.ERROR_WIDGET_DISPOSED ); } // [rh] The only method to manipulate the image indent (setImageIndent) is // deprecated and thus not implemented, therefore we can safely return 0 return 0; } /** * Returns a rectangle describing the size and location * relative to its parent of the text at a column in the * table. An empty rectangle is returned if index exceeds * the index of the table's last column. * * @param index the index that specifies the column * @return the receiver's bounding text 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 getTextBounds( final int index ) { checkWidget(); int itemIndex = parent.indexOf( this ); if( !parent.checkData( this, itemIndex ) ) { error( SWT.ERROR_WIDGET_DISPOSED ); } int left = 0; int top = 0; int width = 0; Rectangle cellPadding = parent.getCellPadding(); if( index == 0 && parent.getColumnCount() == 0 ) { int imageWidth = 0; int spacing = 0; if( parent.hasColumnImages( 0 ) ) { imageWidth = parent.getItemImageSize().x; spacing = getSpacing( 0 ); } left = getLeft( 0 ) + cellPadding.x + imageWidth + spacing; top = getTop( itemIndex ); Font font = getFont(); width = Graphics.stringExtent( font, getText( 0 ) ).x; } else if( itemIndex != -1 && index < parent.getColumnCount() ) { int imageWidth = 0; if( parent.hasColumnImages( index ) ) { imageWidth = parent.getItemImageSize().x; } int spacing = getSpacing( index ); left = getLeft( index ) + cellPadding.x + imageWidth + spacing; top = getTop( itemIndex ); width = getColumnWidth( index ) - cellPadding.width - imageWidth - spacing; if( width < 0 ) { width = 0; } } int height = getHeight( index ); return new Rectangle( left, top, width, height ); } private int getColumnWidth( final int index ) { TableColumn column = parent.getColumn( index ); return column.getWidth() - getCheckWidth( index ); } private int getLeft( final int index ) { int result = 0; int columnCount = parent.getColumnCount(); if( index == 0 && columnCount == 0 ) { result = getCheckWidth( index ) - parent.leftOffset; } else if( index >= 0 && index < columnCount ) { // TODO [rh] consider applying the leftOffset already in Column#getLeft() int columnLeft = parent.getColumn( index ).getLeft(); result = getCheckWidth( index ) + columnLeft - parent.leftOffset; } return result; } private int getTop( final int itemIndex ) { int relativeItemIndex = itemIndex - parent.getTopIndex(); int headerHeight = parent.getHeaderHeight(); int itemHeight = parent.getItemHeight(); return headerHeight + relativeItemIndex * itemHeight; } private int getHeight( final int index ) { int result = 0; int columnCount = parent.getColumnCount(); boolean singleColumn = index == 0 && columnCount == 0; boolean columnInRange = index >= 0 && index < columnCount; if( singleColumn || columnInRange ) { result = parent.getItemHeight(); } return result; } final int getPackWidth( final int index ) { return getImageWidth( index ) + getSpacing( index ) + getTextWidth( index ) + parent.getCellPadding().width; } final int getCheckWidth( final int index ) { return parent.getCheckWidth( index ); } private int getImageWidth( final int index ) { int result = 0; Image image = getImage( index ); if( image != null ) { result = parent.getItemImageSize().x; } return result; } private int getTextWidth( final int index ) { int result = 0; String text = getText( index ); if( text.length() > 0 ) { result = Graphics.stringExtent( parent.getFont(), text ).x; } return result; } private int getSpacing( final int index ) { int result = 0; if( parent.hasColumnImages( index ) ) { result = parent.getCellSpacing(); } return result; } /////////////////////////////////////// // Clear item data (texts, images, etc) final void removeData( final int index ) { if( data != null && parent.getColumnCount() > 1 ) { Data[] newData = new Data[ data.length - 1 ]; System.arraycopy( data, 0, newData, 0, index ); int offSet = data.length - index - 1; System.arraycopy( data, index + 1, newData, index, offSet ); data = newData; } } final void clear() { data = null; checked = false; grayed = false; parent.updateScrollBars(); if( ( parent.style & SWT.VIRTUAL ) != 0 ) { cached = false; parent.redraw(); } } ///////////////////////////// // Widget and Item overrides void releaseParent() { parent.destroyItem( this, parent.indexOf( this ) ); } String getNameText() { if( ( parent.style & SWT.VIRTUAL ) != 0 ) { if( !cached ) { return "*virtual*"; } } return super.getNameText(); } ////////////////// // Helping methods private void markCached() { if( ( parent.style & SWT.VIRTUAL ) != 0 ) { cached = true; } } private void ensureData( final int index, final int columnCount ) { if( data == null ) { data = new Data[ columnCount ]; } else if( data.length < columnCount ) { Data[] newData = new Data[ columnCount ]; System.arraycopy( data, 0, newData, 0, data.length ); data = newData; } if( data[ index ] == null ) { data[ index ] = new Data(); } } private static boolean equals( final Object object1, final Object object2 ) { boolean result; if( object1 == object2 ) { result = true; } else if( object1 == null ) { result = false; } else { result = object1.equals( object2 ); } return result; } private static Table checkNull( final Table table ) { if( table == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } return table; } }