Java tutorial
/******************************************************************************* * Copyright (c) 2002, 2017 Innoopract Informationssysteme GmbH and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Innoopract Informationssysteme GmbH - initial API and implementation * EclipseSource - ongoing development ******************************************************************************/ package org.eclipse.swt.widgets; import static org.eclipse.swt.internal.widgets.MarkupUtil.isMarkupEnabledFor; import static org.eclipse.swt.internal.widgets.MarkupValidator.isValidationDisabledFor; import java.util.Arrays; import org.eclipse.rap.rwt.internal.lifecycle.WidgetLCA; import org.eclipse.rap.rwt.theme.BoxDimensions; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.internal.SerializableCompatibility; import org.eclipse.swt.internal.widgets.ITableItemAdapter; import org.eclipse.swt.internal.widgets.IWidgetColorAdapter; import org.eclipse.swt.internal.widgets.IWidgetFontAdapter; import org.eclipse.swt.internal.widgets.MarkupValidator; import org.eclipse.swt.internal.widgets.tableitemkit.TableItemLCA; /** * 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> * * @since 1.0 */ public class TableItem extends Item { private transient 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(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 * 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(Table parent, int style, int index) { this(parent, style, index, true); } TableItem(Table parent, int style, int index, boolean create) { super(parent, style); this.parent = parent; this.index = index; if (create) { this.parent.createItem(this, index); } } @Override @SuppressWarnings("unchecked") public <T> T getAdapter(Class<T> adapter) { if (adapter == IWidgetFontAdapter.class || adapter == IWidgetColorAdapter.class || adapter == ITableItemAdapter.class) { if (tableItemAdapter == null) { tableItemAdapter = new TableItemAdapter(); } return (T) tableItemAdapter; } if (adapter == WidgetLCA.class) { return (T) TableItemLCA.INSTANCE; } return super.getAdapter(adapter); } /** * 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 @Override public void setText(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(int index, String text) { checkWidget(); if (text == null) { SWT.error(SWT.ERROR_NULL_ARGUMENT); } if (isMarkupEnabledFor(parent) && !isValidationDisabledFor(parent)) { MarkupValidator.getInstance().validate(text); } 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; data[index].textWidth = Data.UNKNOWN_WIDTH; 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(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); } } } @Override 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(int index) { checkWidget(); if (!parent.checkData(this, parent.indexOf(this))) { error(SWT.ERROR_WIDGET_DISPOSED); } String result = ""; if (hasData(index)) { result = data[index].text; } return result; } //////////////////////////// // Methods to get/set images @Override public void setImage(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(int index, 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(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]); } } @Override 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(int index) { checkWidget(); if (!parent.checkData(this, parent.indexOf(this))) { error(SWT.ERROR_WIDGET_DISPOSED); } return getImageInternal(index); } Image getImageInternal(int index) { Image result = null; if (hasData(index)) { 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(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(); // TODO [rst] Replace with local index field access 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(int index, 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(int index) { checkWidget(); if (!parent.checkData(this, parent.indexOf(this))) { error(SWT.ERROR_WIDGET_DISPOSED); } Color result = getBackground(); if (hasData(index) && 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(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(int index, 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(int index) { checkWidget(); if (!parent.checkData(this, parent.indexOf(this))) { error(SWT.ERROR_WIDGET_DISPOSED); } Color result = getForeground(); if (hasData(index) && 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(Font font) { checkWidget(); if (font != null && font.isDisposed()) { error(SWT.ERROR_INVALID_ARGUMENT); } if (!equals(this.font, font)) { this.font = font; clearTextWidths(); 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(int index, 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; data[index].textWidth = Data.UNKNOWN_WIDTH; 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(int index) { checkWidget(); if (!parent.checkData(this, parent.indexOf(this))) { error(SWT.ERROR_WIDGET_DISPOSED); } Font result = getFont(); if (hasData(index) && 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(boolean checked) { checkWidget(); if ((parent.style & SWT.CHECK) != 0) { if (this.checked != checked) { this.checked = checked; markCached(); } } } /** * 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(boolean grayed) { checkWidget(); if ((parent.style & SWT.CHECK) != 0) { if (this.grayed != grayed) { this.grayed = grayed; markCached(); } } } /** * 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(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); BoxDimensions padding = parent.getCellPadding(); width = imageBounds.width + spacing + textBounds.width + padding.left + padding.right; } 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(int index) { checkWidget(); if (!parent.checkData(this, parent.indexOf(this))) { error(SWT.ERROR_WIDGET_DISPOSED); } int itemIndex = parent.indexOf(this); BoxDimensions cellPadding = parent.getCellPadding(); int left = getLeft(index) + cellPadding.left; 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(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; BoxDimensions 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.left + imageWidth + spacing; top = getTop(itemIndex); width = getTextWidth(0, getFont()); } 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.left + imageWidth + spacing; top = getTop(itemIndex); width = getColumnWidth(index) - cellPadding.left - cellPadding.right - imageWidth - spacing; if (width < 0) { width = 0; } } int height = getHeight(index); return new Rectangle(left, top, width, height); } private int getColumnWidth(int index) { TableColumn column = parent.getColumn(index); return column.getWidth() - getCheckWidth(index); } private int getLeft(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.getColumnLeftOffset(index); } return result; } private int getTop(int itemIndex) { int relativeItemIndex = itemIndex - parent.getTopIndex(); int headerHeight = parent.getHeaderHeight(); int itemHeight = parent.getItemHeight(); return headerHeight + relativeItemIndex * itemHeight; } private int getHeight(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(int index) { BoxDimensions cellPadding = parent.getCellPadding(); return getImageWidth(index) + getSpacing(index) + getTextWidth(index, parent.getFont()) + cellPadding.left + cellPadding.right; } final int getCheckWidth(int index) { return parent.getCheckSize(index).x; } private int getImageWidth(int index) { int result = 0; Image image = getImage(index); if (image != null) { result = parent.getItemImageSize().x; } return result; } private int getTextWidth(int index, Font font) { int result = 0; if (hasData(index)) { if (data[index].textWidth == Data.UNKNOWN_WIDTH) { data[index].textWidth = parent.getStringExtent(font, data[index].text).x; } result = data[index].textWidth; } return result; } void clearTextWidths() { if (data != null) { for (int i = 0; i < data.length; i++) { if (data[i] != null) { data[i].textWidth = Data.UNKNOWN_WIDTH; } } } } boolean hasTextWidthBuffer(int index) { if (hasData(index)) { return data[index].textWidth != Data.UNKNOWN_WIDTH; } return false; } private int getSpacing(int index) { int result = 0; if (parent.hasColumnImages(index)) { result = parent.getCellSpacing(); } return result; } //////////////////////////////////////// // Manage item data (texts, images, etc) final void shiftData(int index) { if (data != null && data.length > index && parent.getColumnCount() > 1) { Data[] newData = new Data[data.length + 1]; System.arraycopy(data, 0, newData, 0, index); int offSet = data.length - index; System.arraycopy(data, index, newData, index + 1, offSet); data = newData; } } final void removeData(int index) { if (data != null && data.length > index && 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 @Override void releaseParent() { parent.destroyItem(this, parent.indexOf(this)); } @Override 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(int index, 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 boolean hasData(int index) { return data != null && index >= 0 && index < data.length && data[index] != null; } private static boolean equals(Object object1, 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(Table table) { if (table == null) { SWT.error(SWT.ERROR_NULL_ARGUMENT); } return table; } private class TableItemAdapter implements ITableItemAdapter, IWidgetFontAdapter, IWidgetColorAdapter { @Override public Color getUserBackground() { return background; } @Override public Color getUserForeground() { return foreground; } @Override public Font getUserFont() { return font; } @Override public String[] getTexts() { int columnCount = Math.max(1, getParent().getColumnCount()); String[] result = null; if (data != null) { for (int i = 0; i < data.length; i++) { String text = data[i] == null ? "" : data[i].text; if (!"".equals(text)) { if (result == null) { result = new String[columnCount]; Arrays.fill(result, ""); } result[i] = text; } } } return result; } @Override public Image[] getImages() { int columnCount = Math.max(1, getParent().getColumnCount()); Image[] result = null; if (data != null) { for (int i = 0; i < data.length; i++) { Image image = data[i] == null ? null : data[i].image; if (image != null) { if (result == null) { result = new Image[columnCount]; } result[i] = image; } } } return result; } @Override public Color[] getCellBackgrounds() { int columnCount = Math.max(1, getParent().getColumnCount()); Color[] result = null; if (data != null) { for (int i = 0; i < data.length; i++) { Color background = data[i] == null ? null : data[i].background; if (background != null) { if (result == null) { result = new Color[columnCount]; } result[i] = background; } } } return result; } @Override public Color[] getCellForegrounds() { int columnCount = Math.max(1, getParent().getColumnCount()); Color[] result = null; if (data != null) { for (int i = 0; i < data.length; i++) { Color foreground = data[i] == null ? null : data[i].foreground; if (foreground != null) { if (result == null) { result = new Color[columnCount]; } result[i] = foreground; } } } return result; } @Override public Font[] getCellFonts() { int columnCount = Math.max(1, getParent().getColumnCount()); Font[] result = null; if (data != null) { for (int i = 0; i < data.length; i++) { Font font = data[i] == null ? null : data[i].font; if (font != null) { if (result == null) { result = new Font[columnCount]; } result[i] = font; } } } return result; } } private static final class Data implements SerializableCompatibility { static final int UNKNOWN_WIDTH = -1; String text = ""; int textWidth = UNKNOWN_WIDTH; Image image; Font font; Color background; Color foreground; } }