Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.swt/Eclipse SWT/emulated/treetable/org/eclipse/swt/widgets/TableItem.java')
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/emulated/treetable/org/eclipse/swt/widgets/TableItem.java2032
1 files changed, 2032 insertions, 0 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/emulated/treetable/org/eclipse/swt/widgets/TableItem.java b/bundles/org.eclipse.swt/Eclipse SWT/emulated/treetable/org/eclipse/swt/widgets/TableItem.java
new file mode 100644
index 0000000000..e4c3476995
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/emulated/treetable/org/eclipse/swt/widgets/TableItem.java
@@ -0,0 +1,2032 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * 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>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#table">Table, TableItem, TableColumn snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class TableItem extends Item {
+ Table parent;
+ int index = -1;
+ boolean checked, grayed, cached;
+
+ String[] texts;
+ int[] textWidths = new int [1]; /* cached string measurements */
+ int customWidth = -1; /* width specified by Measure callback */
+ int fontHeight; /* cached item font height */
+ int[] fontHeights;
+ int imageIndent;
+ Image[] images;
+ Color foreground, background;
+ String[] displayTexts;
+ Color[] cellForegrounds, cellBackgrounds;
+ Font font;
+ Font[] cellFonts;
+
+ static final int MARGIN_TEXT = 3; /* the left and right margins within the text's space */
+
+/**
+ * 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).itemsCount);
+}
+/**
+ * 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 notifyParent) {
+ super (parent, style);
+ int validItemIndex = parent.itemsCount;
+ if (!(0 <= index && index <= validItemIndex)) error (SWT.ERROR_INVALID_RANGE);
+ this.parent = parent;
+ this.index = index;
+ int columnCount = parent.columns.length;
+ if (columnCount > 0) {
+ displayTexts = new String [columnCount];
+ if (columnCount > 1) {
+ texts = new String [columnCount];
+ textWidths = new int [columnCount];
+ images = new Image [columnCount];
+ }
+ }
+ if (notifyParent) parent.createItem (this);
+}
+/*
+ * Updates internal structures in the receiver and its child items to handle the creation of a new column.
+ */
+void addColumn (TableColumn column) {
+ int index = column.getIndex ();
+ int columnCount = parent.columns.length;
+
+ if (columnCount > 1) {
+ if (columnCount == 2) {
+ texts = new String [2];
+ } else {
+ String[] newTexts = new String [columnCount];
+ System.arraycopy (texts, 0, newTexts, 0, index);
+ System.arraycopy (texts, index, newTexts, index + 1, columnCount - index - 1);
+ texts = newTexts;
+ }
+ if (index == 0) {
+ texts [1] = text;
+ text = ""; //$NON-NLS-1$
+ }
+
+ if (columnCount == 2) {
+ images = new Image [2];
+ } else {
+ Image[] newImages = new Image [columnCount];
+ System.arraycopy (images, 0, newImages, 0, index);
+ System.arraycopy (images, index, newImages, index + 1, columnCount - index - 1);
+ images = newImages;
+ }
+ if (index == 0) {
+ images [1] = image;
+ image = null;
+ }
+
+ int[] newTextWidths = new int [columnCount];
+ System.arraycopy (textWidths, 0, newTextWidths, 0, index);
+ System.arraycopy (textWidths, index, newTextWidths, index + 1, columnCount - index - 1);
+ textWidths = newTextWidths;
+ } else {
+ customWidth = -1; /* columnCount == 1 */
+ }
+
+ /*
+ * The length of displayTexts always matches the parent's column count, unless this
+ * count is zero, in which case displayTexts is null.
+ */
+ String[] newDisplayTexts = new String [columnCount];
+ if (columnCount > 1) {
+ System.arraycopy (displayTexts, 0, newDisplayTexts, 0, index);
+ System.arraycopy (displayTexts, index, newDisplayTexts, index + 1, columnCount - index - 1);
+ }
+ displayTexts = newDisplayTexts;
+
+ if (cellBackgrounds != null) {
+ Color[] newCellBackgrounds = new Color [columnCount];
+ System.arraycopy (cellBackgrounds, 0, newCellBackgrounds, 0, index);
+ System.arraycopy (cellBackgrounds, index, newCellBackgrounds, index + 1, columnCount - index - 1);
+ cellBackgrounds = newCellBackgrounds;
+ }
+ if (cellForegrounds != null) {
+ Color[] newCellForegrounds = new Color [columnCount];
+ System.arraycopy (cellForegrounds, 0, newCellForegrounds, 0, index);
+ System.arraycopy (cellForegrounds, index, newCellForegrounds, index + 1, columnCount - index - 1);
+ cellForegrounds = newCellForegrounds;
+ }
+ if (cellFonts != null) {
+ Font[] newCellFonts = new Font [columnCount];
+ System.arraycopy (cellFonts, 0, newCellFonts, 0, index);
+ System.arraycopy (cellFonts, index, newCellFonts, index + 1, columnCount - index - 1);
+ cellFonts = newCellFonts;
+
+ int[] newFontHeights = new int [columnCount];
+ System.arraycopy (fontHeights, 0, newFontHeights, 0, index);
+ System.arraycopy (fontHeights, index, newFontHeights, index + 1, columnCount - index - 1);
+ fontHeights = newFontHeights;
+ }
+
+ if (index == 0 && columnCount > 1) {
+ /*
+ * The new second column may have more width available to it than it did when it was
+ * the first column if checkboxes are being shown, so recompute its displayText if needed.
+ */
+ if ((parent.style & SWT.CHECK) != 0) {
+ GC gc = new GC (parent);
+ gc.setFont (getFont (1, false));
+ computeDisplayText (1, gc);
+ gc.dispose ();
+ }
+ }
+}
+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);
+}
+void clear () {
+ checked = grayed = false;
+ texts = null;
+ textWidths = new int [1];
+ fontHeight = 0;
+ fontHeights = null;
+ images = null;
+ foreground = background = null;
+ displayTexts = null;
+ cellForegrounds = cellBackgrounds = null;
+ font = null;
+ cellFonts = null;
+ cached = false;
+ text = "";
+ image = null;
+
+ int columnCount = parent.columns.length;
+ if (columnCount > 0) {
+ displayTexts = new String [columnCount];
+ if (columnCount > 1) {
+ texts = new String [columnCount];
+ textWidths = new int [columnCount];
+ images = new Image [columnCount];
+ }
+ }
+}
+void computeDisplayText (int columnIndex, GC gc) {
+ if ((parent.style & SWT.VIRTUAL) != 0 && !cached) return; /* nothing to do */
+
+ int columnCount = parent.columns.length;
+ if (columnCount == 0) {
+ String text = getText (0, false);
+ textWidths [columnIndex] = gc.stringExtent (text).x;
+ return;
+ }
+
+ TableColumn column = parent.columns [columnIndex];
+ int availableWidth = column.width - 2 * parent.getCellPadding () - 2 * MARGIN_TEXT;
+ if (columnIndex == 0) {
+ availableWidth -= parent.col0ImageWidth;
+ if (parent.col0ImageWidth > 0) availableWidth -= Table.MARGIN_IMAGE;
+ if ((parent.style & SWT.CHECK) != 0) {
+ availableWidth -= parent.checkboxBounds.width;
+ availableWidth -= Table.MARGIN_IMAGE;
+ }
+ } else {
+ Image image = getImage (columnIndex, false);
+ if (image != null) {
+ availableWidth -= image.getBounds ().width;
+ availableWidth -= Table.MARGIN_IMAGE;
+ }
+ }
+
+ String text = getText (columnIndex, false);
+ int textWidth = gc.stringExtent (text).x;
+ if (textWidth <= availableWidth) {
+ displayTexts [columnIndex] = text;
+ textWidths [columnIndex] = textWidth;
+ return;
+ }
+
+ /* Ellipsis will be needed, so subtract their width from the available text width */
+ int ellipsisWidth = gc.stringExtent (Table.ELLIPSIS).x;
+ availableWidth -= ellipsisWidth;
+ if (availableWidth <= 0) {
+ displayTexts [columnIndex] = Table.ELLIPSIS;
+ textWidths [columnIndex] = ellipsisWidth;
+ return;
+ }
+
+ /* Make initial guess. */
+ int index = Math.min (availableWidth / gc.getFontMetrics ().getAverageCharWidth (), text.length ());
+ textWidth = gc.stringExtent (text.substring (0, index)).x;
+
+ /* Initial guess is correct. */
+ if (availableWidth == textWidth) {
+ displayTexts [columnIndex] = text.substring (0, index) + Table.ELLIPSIS;
+ textWidths [columnIndex] = textWidth + ellipsisWidth;
+ return;
+ }
+
+ /* Initial guess is too high, so reduce until fit is found. */
+ if (availableWidth < textWidth) {
+ do {
+ index--;
+ if (index < 0) {
+ displayTexts [columnIndex] = Table.ELLIPSIS;
+ textWidths [columnIndex] = ellipsisWidth;
+ return;
+ }
+ text = text.substring (0, index);
+ textWidth = gc.stringExtent (text).x;
+ } while (availableWidth < textWidth);
+ displayTexts [columnIndex] = text + Table.ELLIPSIS;
+ textWidths [columnIndex] = textWidth + ellipsisWidth;
+ return;
+ }
+
+ /* Initial guess is too low, so increase until overrun is found. */
+ int previousWidth = 0;
+ while (textWidth < availableWidth) {
+ index++;
+ previousWidth = textWidth;
+ textWidth = gc.stringExtent (text.substring (0, index)).x;
+ }
+ displayTexts [columnIndex] = text.substring (0, index - 1) + Table.ELLIPSIS;
+ textWidths [columnIndex] = previousWidth + ellipsisWidth;
+}
+void computeDisplayTexts (GC gc) {
+ if ((parent.style & SWT.VIRTUAL) != 0 && !cached) return; /* nothing to do */
+
+ int columnCount = parent.columns.length;
+ if (columnCount == 0) return;
+
+ for (int i = 0; i < columnCount; i++) {
+ gc.setFont (getFont (i, false));
+ computeDisplayText (i, gc);
+ }
+}
+/*
+ * Computes the cached text widths.
+ */
+void computeTextWidths (GC gc) {
+ if ((parent.style & SWT.VIRTUAL) != 0 && !cached) return; /* nothing to do */
+
+ int validColumnCount = Math.max (1, parent.columns.length);
+ textWidths = new int [validColumnCount];
+ for (int i = 0; i < textWidths.length; i++) {
+ String value = getDisplayText (i);
+ if (value != null) {
+ gc.setFont (getFont (i, false));
+ textWidths [i] = gc.stringExtent (value).x;
+ }
+ }
+}
+public void dispose () {
+ if (isDisposed ()) return;
+ Table parent = this.parent;
+ int startIndex = index;
+ int endIndex = parent.itemsCount - 1;
+ dispose (true);
+ parent.redrawItems (startIndex, endIndex, false);
+}
+void dispose (boolean notifyParent) {
+ if (isDisposed ()) return;
+ if (notifyParent) parent.destroyItem (this);
+ super.dispose (); /* super is intentional here */
+ background = foreground = null;
+ cellBackgrounds = cellForegrounds = null;
+ font = null;
+ cellFonts = null;
+ images = null;
+ texts = displayTexts = null;
+ textWidths = fontHeights = null;
+ parent = null;
+}
+/**
+ * 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>
+ *
+ * @since 2.0
+ */
+public Color getBackground () {
+ checkWidget ();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if (background != null) return background;
+ return parent.getBackground ();
+}
+/**
+ * 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>
+ *
+ * @since 3.0
+ */
+public Color getBackground (int columnIndex) {
+ checkWidget ();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int validColumnCount = Math.max (1, parent.columns.length);
+ if (!(0 <= columnIndex && columnIndex < validColumnCount)) return getBackground ();
+ if (cellBackgrounds == null || cellBackgrounds [columnIndex] == null) return getBackground ();
+ return cellBackgrounds [columnIndex];
+}
+/**
+ * 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>
+ *
+ * @since 3.2
+ */
+public Rectangle getBounds () {
+ checkWidget ();
+ return getBounds (true);
+}
+Rectangle getBounds (boolean checkData) {
+ if (checkData && !parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int x = getTextX (0);
+ int width = textWidths [0] + 2 * MARGIN_TEXT;
+ if (parent.columns.length > 0) {
+ TableColumn column = parent.columns [0];
+ int right = column.getX () + column.width;
+ if (x + width > right) {
+ width = Math.max (0, right - x);
+ }
+ }
+ return new Rectangle (x, parent.getItemY (this), width, parent.itemHeight);
+}
+/**
+ * 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 columnIndex) {
+ checkWidget ();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ TableColumn[] columns = parent.columns;
+ int columnCount = columns.length;
+ int validColumnCount = Math.max (1, columnCount);
+ if (!(0 <= columnIndex && columnIndex < validColumnCount)) {
+ return new Rectangle (0, 0, 0, 0);
+ }
+ /*
+ * If there are no columns then this is the bounds of the receiver's content.
+ */
+ if (columnCount == 0) {
+ int width = getContentWidth (0);
+ return new Rectangle (
+ getContentX (0),
+ parent.getItemY (this),
+ width,
+ parent.itemHeight - 1);
+ }
+
+ TableColumn column = columns [columnIndex];
+ if (columnIndex == 0) {
+ /*
+ * For column 0 this is bounds from the beginning of the content to the
+ * end of the column.
+ */
+ int x = getContentX (0);
+ int offset = x - column.getX ();
+ int width = Math.max (0, column.width - offset - 1); /* max is for columns with small widths */
+ return new Rectangle (x, parent.getItemY (this) + 1, width, parent.itemHeight - 1);
+ }
+ /*
+ * For columns > 0 this is the bounds of the table cell.
+ */
+ return new Rectangle (column.getX (), parent.getItemY (this) + 1, column.width, parent.itemHeight - 1);
+}
+/*
+ * Returns the full bounds of a cell in a table, regardless of its content.
+ */
+Rectangle getCellBounds (int columnIndex) {
+ int y = parent.getItemY (this);
+ if (parent.columns.length == 0) {
+ int width;
+ if (customWidth != -1) {
+ width = getContentX (0) + customWidth + parent.horizontalOffset;
+ } else {
+ int textPaintWidth = textWidths [0] + 2 * MARGIN_TEXT;
+ width = getTextX (0) + textPaintWidth + parent.horizontalOffset;
+ }
+ return new Rectangle (-parent.horizontalOffset, y, width, parent.itemHeight);
+ }
+ TableColumn column = parent.columns [columnIndex];
+ return new Rectangle (column.getX (), y, column.width, parent.itemHeight);
+}
+/*
+ * Returns the bounds of the receiver's checkbox, or null if the parent's style does not
+ * include SWT.CHECK.
+ */
+Rectangle getCheckboxBounds () {
+ if ((parent.getStyle () & SWT.CHECK) == 0) return null;
+ Rectangle result = parent.checkboxBounds;
+ if (parent.columns.length == 0) {
+ result.x = parent.getCellPadding () - parent.horizontalOffset;
+ } else {
+ result.x = parent.columns [0].getX () + parent.getCellPadding ();
+ }
+ result.y = parent.getItemY (this) + (parent.itemHeight - result.height) / 2;
+ return result;
+}
+/**
+ * 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, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return checked;
+}
+int getContentWidth (int columnIndex) {
+ int width = textWidths [columnIndex] + 2 * MARGIN_TEXT;
+ if (columnIndex == 0) {
+ width += parent.col0ImageWidth;
+ if (parent.col0ImageWidth > 0) width += Table.MARGIN_IMAGE;
+ } else {
+ Image image = getImage (columnIndex, false);
+ if (image != null) {
+ width += image.getBounds ().width + Table.MARGIN_IMAGE;
+ }
+ }
+ return width;
+}
+/*
+ * Returns the x value where the receiver's content (ie.- its image or text) begins
+ * for the specified column.
+ */
+int getContentX (int columnIndex) {
+ int minX = parent.getCellPadding ();
+ if (columnIndex == 0) {
+ Rectangle checkboxBounds = getCheckboxBounds ();
+ if (checkboxBounds != null) {
+ minX += checkboxBounds.width + Table.MARGIN_IMAGE;
+ }
+ }
+
+ if (parent.columns.length == 0) return minX - parent.horizontalOffset; /* free first column */
+
+ TableColumn column = parent.columns [columnIndex];
+ int columnX = column.getX ();
+ if ((column.style & SWT.LEFT) != 0) return columnX + minX;
+
+ /* column is not left-aligned */
+ int contentWidth = getContentWidth (columnIndex);
+ int contentX = 0;
+ if ((column.style & SWT.RIGHT) != 0) {
+ contentX = column.width - parent.getCellPadding () - contentWidth;
+ } else { /* SWT.CENTER */
+ contentX = (column.width - contentWidth) / 2;
+ }
+ return Math.max (columnX + minX, columnX + contentX);
+}
+String getDisplayText (int columnIndex) {
+ if (parent.columns.length == 0) return getText (0, false);
+ String result = displayTexts [columnIndex];
+ return result != null ? result : ""; //$NON-NLS-1$
+}
+/*
+ * Returns the bounds that should be used for drawing a focus rectangle on the receiver
+ */
+Rectangle getFocusBounds () {
+ int x = 0;
+ TableColumn[] columns = parent.columns;
+ int[] columnOrder = parent.getColumnOrder ();
+ if ((parent.style & SWT.FULL_SELECTION) != 0) {
+ int col0index = columnOrder.length == 0 ? 0 : columnOrder [0];
+ if (col0index == 0) {
+ x = getTextX (0);
+ } else {
+ x = -parent.horizontalOffset;
+ }
+ } else {
+ x = getTextX (0);
+ }
+
+ if (columns.length > 0) {
+ /* ensure that the focus x does not start beyond the right bound of column 0 */
+ int rightX = columns [0].getX () + columns [0].width;
+ x = Math.min (x, rightX - 1);
+ }
+
+ int width;
+ if (columns.length == 0) {
+ if (customWidth != -1) {
+ width = customWidth;
+ } else {
+ width = textWidths [0] + 2 * MARGIN_TEXT;
+ }
+ } else {
+ TableColumn column;
+ if ((parent.style & SWT.FULL_SELECTION) != 0) {
+ column = columns [columnOrder [columnOrder.length - 1]];
+ } else {
+ column = columns [0];
+ }
+ width = column.getX () + column.width - x - 1;
+ }
+ return new Rectangle (
+ x,
+ parent.getItemY (this) + (parent.linesVisible ? 1 : 0),
+ width,
+ parent.itemHeight - (parent.linesVisible ? 1 : 0));
+}
+/**
+ * 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>
+ *
+ * @since 3.0
+ */
+public Font getFont () {
+ checkWidget ();
+ return getFont (true);
+}
+Font getFont (boolean checkData) {
+ if (checkData && !parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if (font != null) return font;
+ return parent.getFont ();
+}
+/**
+ * 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>
+ *
+ * @since 3.0
+ */
+public Font getFont (int columnIndex) {
+ checkWidget ();
+ return getFont (columnIndex, true);
+}
+Font getFont (int columnIndex, boolean checkData) {
+ if (checkData && !parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int validColumnCount = Math.max (1, parent.columns.length);
+ if (!(0 <= columnIndex && columnIndex < validColumnCount)) return getFont (checkData);
+ if (cellFonts == null || cellFonts [columnIndex] == null) return getFont (checkData);
+ return cellFonts [columnIndex];
+}
+int getFontHeight () {
+ if (fontHeight != 0) return fontHeight;
+ return parent.fontHeight;
+}
+int getFontHeight (int columnIndex) {
+ if (fontHeights == null || fontHeights [columnIndex] == 0) return getFontHeight ();
+ return fontHeights [columnIndex];
+}
+/**
+ * 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>
+ *
+ * @since 2.0
+ */
+public Color getForeground () {
+ checkWidget ();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if (foreground != null) return foreground;
+ return parent.getForeground ();
+}
+/**
+ *
+ * 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>
+ *
+ * @since 3.0
+ */
+public Color getForeground (int columnIndex) {
+ checkWidget ();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int validColumnCount = Math.max (1, parent.columns.length);
+ if (!(0 <= columnIndex && columnIndex < validColumnCount)) return getForeground ();
+ if (cellForegrounds == null || cellForegrounds [columnIndex] == null) return getForeground ();
+ return cellForegrounds [columnIndex];
+}
+/**
+ * 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, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return grayed;
+}
+/*
+ * Returns the bounds representing the clickable region that should select the receiver.
+ */
+Rectangle getHitBounds () {
+ int[] columnOrder = parent.getColumnOrder ();
+ int contentX = 0;
+ if ((parent.style & SWT.FULL_SELECTION) != 0) {
+ int col0index = columnOrder.length == 0 ? 0 : columnOrder [0];
+ if (col0index == 0) {
+ contentX = getContentX (0);
+ } else {
+ contentX = 0;
+ }
+ } else {
+ contentX = getContentX (0);
+ }
+
+ int width = 0;
+ TableColumn[] columns = parent.columns;
+ if (columns.length == 0) {
+ width = getContentWidth (0);
+ } else {
+ /*
+ * If there are columns then this spans from the beginning of the receiver's column 0
+ * image or text to the end of either column 0 or the last column (FULL_SELECTION).
+ */
+ TableColumn column;
+ if ((parent.style & SWT.FULL_SELECTION) != 0) {
+ column = columns [columnOrder [columnOrder.length - 1]];
+ } else {
+ column = columns [0];
+ }
+ width = column.getX () + column.width - contentX;
+ }
+ return new Rectangle (contentX, parent.getItemY (this), width, parent.itemHeight);
+}
+public Image getImage () {
+ checkWidget ();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return super.getImage ();
+}
+/**
+ * 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 columnIndex) {
+ checkWidget ();
+ return getImage (columnIndex, true);
+}
+Image getImage (int columnIndex, boolean checkData) {
+ if (checkData && !parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int validColumnCount = Math.max (1, parent.columns.length);
+ if (!(0 <= columnIndex && columnIndex < validColumnCount)) return null;
+ if (columnIndex == 0) return super.getImage (); /* super is intentional here */
+ return images [columnIndex];
+}
+/**
+ * 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 columnIndex) {
+ checkWidget ();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int validColumnCount = Math.max (1, parent.columns.length);
+ if (!(0 <= columnIndex && columnIndex < validColumnCount)) return new Rectangle (0,0,0,0);
+
+ int padding = parent.getCellPadding ();
+ int startX = getContentX (columnIndex);
+ int itemHeight = parent.itemHeight;
+ int imageSpaceY = itemHeight - 2 * padding;
+ int y = parent.getItemY (this);
+ Image image = getImage (columnIndex, false);
+ int drawWidth = 0;
+ if (columnIndex == 0) {
+ /* for column 0 all images have the same width */
+ drawWidth = parent.col0ImageWidth;
+ } else {
+ if (image != null) drawWidth = image.getBounds ().width;
+ }
+ return new Rectangle (startX, y + padding, drawWidth, imageSpaceY);
+}
+/**
+ * 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, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return imageIndent; // TODO
+}
+String getNameText () {
+ if ((parent.style & SWT.VIRTUAL) != 0) {
+ if (!cached) return "*virtual*"; //$NON-NLS-1$
+ }
+ return super.getNameText ();
+}
+/**
+ * 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;
+}
+/*
+ * Returns the receiver's ideal width for the specified columnIndex.
+ */
+int getPreferredWidth (int columnIndex) {
+ int width = 0;
+ GC gc = new GC (parent);
+ gc.setFont (getFont (columnIndex, false));
+ width += gc.stringExtent (getText (columnIndex, false)).x + 2 * MARGIN_TEXT;
+ if (columnIndex == 0) {
+ if (parent.col0ImageWidth > 0) {
+ width += parent.col0ImageWidth;
+ width += Table.MARGIN_IMAGE;
+ }
+ } else {
+ Image image = getImage (columnIndex, false);
+ if (image != null) {
+ width += image.getBounds ().width;
+ width += Table.MARGIN_IMAGE;
+ }
+ }
+
+ if (parent.hooks (SWT.MeasureItem)) {
+ Event event = new Event ();
+ event.item = this;
+ event.gc = gc;
+ event.index = columnIndex;
+ event.x = getContentX (columnIndex);
+ event.y = parent.getItemY (this);
+ event.width = width;
+ event.height = parent.itemHeight;
+ parent.sendEvent (SWT.MeasureItem, event);
+ if (parent.itemHeight != event.height) {
+ parent.customHeightSet = true;
+ boolean update = parent.setItemHeight (event.height + 2 * parent.getCellPadding ());
+ if (update) parent.redraw ();
+ }
+ width = event.width;
+ }
+
+ gc.dispose ();
+ if (columnIndex == 0 && (parent.style & SWT.CHECK) != 0) {
+ width += parent.checkboxBounds.width;
+ width += Table.MARGIN_IMAGE;
+ }
+ return width + 2 * parent.getCellPadding ();
+}
+public String getText () {
+ checkWidget ();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return super.getText ();
+}
+/**
+ * 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 columnIndex) {
+ checkWidget ();
+ return getText (columnIndex, true);
+}
+String getText (int columnIndex, boolean checkData) {
+ if (checkData && !parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int validColumnCount = Math.max (1, parent.columns.length);
+ if (!(0 <= columnIndex && columnIndex < validColumnCount)) return ""; //$NON-NLS-1$
+ if (columnIndex == 0) return super.getText (); /* super is intentional here */
+ if (texts [columnIndex] == null) return ""; //$NON-NLS-1$
+ return texts [columnIndex];
+}
+/**
+ * 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>
+ *
+ * @since 3.3
+ */
+public Rectangle getTextBounds (int columnIndex) {
+ checkWidget ();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ TableColumn[] columns = parent.columns;
+ int columnCount = columns.length;
+ int validColumnCount = Math.max (1, columnCount);
+ if (!(0 <= columnIndex && columnIndex < validColumnCount)) {
+ return new Rectangle (0, 0, 0, 0);
+ }
+ /*
+ * If there are no columns then this is the bounds of the receiver's content,
+ * starting from the text.
+ */
+ if (columnCount == 0) {
+ int x = getTextX (0) + MARGIN_TEXT;
+ int width = Math.max (0, getContentX(0) + getContentWidth (0) - x);
+ return new Rectangle (
+ x,
+ parent.getItemY (this),
+ width,
+ parent.itemHeight - 1);
+ }
+
+ TableColumn column = columns [columnIndex];
+ if (columnIndex == 0) {
+ /*
+ * For column 0 this is bounds from the beginning of the content to the
+ * end of the column, starting from the text.
+ */
+ int x = getTextX (0) + MARGIN_TEXT;
+ int offset = x - column.getX ();
+ int width = Math.max (0, column.width - offset - 1); /* max is for columns with small widths */
+ return new Rectangle (x, parent.getItemY (this) + 1, width, parent.itemHeight - 1);
+ }
+ /*
+ * For columns > 0 this is the bounds of the table cell, starting from the text.
+ */
+ int x = getTextX (columnIndex) + MARGIN_TEXT;
+ int offset = x - column.getX ();
+ int width = Math.max (0, column.width - offset - MARGIN_TEXT);
+ return new Rectangle (x, parent.getItemY (this) + 1, width, parent.itemHeight - 1);
+}
+/*
+ * Returns the x value where the receiver's text begins.
+ */
+int getTextX (int columnIndex) {
+ int textX = getContentX (columnIndex);
+ if (columnIndex == 0) {
+ textX += parent.col0ImageWidth;
+ if (parent.col0ImageWidth > 0) textX += Table.MARGIN_IMAGE;
+ } else {
+ Image image = getImage (columnIndex, false);
+ if (image != null) {
+ textX += image.getBounds ().width + Table.MARGIN_IMAGE;
+ }
+ }
+ return textX;
+}
+/*
+ * Answers a boolean indicating whether the receiver's y is within the current
+ * viewport of the parent.
+ */
+boolean isInViewport () {
+ int topIndex = parent.topIndex;
+ if (index < topIndex) return false;
+ int visibleCount = parent.clientArea.height / parent.itemHeight;
+ return index <= topIndex + visibleCount;
+}
+boolean isSelected () {
+ return parent.getSelectionIndex (this) != -1;
+}
+/*
+ * The backgroundOnly argument indicates whether the item should only
+ * worry about painting its background color and selection.
+ *
+ * Returns a boolean indicating whether to abort drawing focus on the item.
+ * If the receiver is not the current focus item then this value is irrelevant.
+ */
+boolean paint (GC gc, TableColumn column, boolean backgroundOnly) {
+ if (!parent.checkData (this, true)) return false;
+ int columnIndex = 0, x = 0;
+ if (column != null) {
+ columnIndex = column.getIndex ();
+ x = column.getX ();
+ }
+
+ /*
+ * Capture GC attributes that will need to be restored later in the paint
+ * process to ensure that the item paints as intended without being affected
+ * by GC changes made in MeasureItem/EraseItem/PaintItem callbacks.
+ */
+ int oldAlpha = gc.getAlpha ();
+ boolean oldAdvanced = gc.getAdvanced ();
+ int oldAntialias = gc.getAntialias ();
+ Pattern oldBackgroundPattern = gc.getBackgroundPattern ();
+ Pattern oldForegroundPattern = gc.getForegroundPattern ();
+ int oldInterpolation = gc.getInterpolation ();
+ int oldTextAntialias = gc.getTextAntialias ();
+
+ if (parent.hooks (SWT.MeasureItem)) {
+ int contentWidth = getContentWidth (columnIndex);
+ int contentX = getContentX (columnIndex);
+ gc.setFont (getFont (columnIndex, false));
+ Event event = new Event ();
+ event.item = this;
+ event.gc = gc;
+ event.index = columnIndex;
+ event.x = contentX;
+ event.y = parent.getItemY (this);
+ event.width = contentWidth;
+ event.height = parent.itemHeight;
+ parent.sendEvent (SWT.MeasureItem, event);
+ event.gc = null;
+ if (gc.isDisposed ()) return false;
+ gc.setAlpha (oldAlpha);
+ gc.setAntialias (oldAntialias);
+ gc.setBackgroundPattern (oldBackgroundPattern);
+ gc.setForegroundPattern (oldForegroundPattern);
+ gc.setInterpolation (oldInterpolation);
+ gc.setTextAntialias (oldTextAntialias);
+ gc.setAdvanced (oldAdvanced);
+ if (isDisposed ()) return false;
+ if (parent.itemHeight != event.height) {
+ parent.customHeightSet = true;
+ boolean update = parent.setItemHeight (event.height + 2 * parent.getCellPadding ());
+ if (update) parent.redraw ();
+ }
+ if (parent.columns.length == 0) {
+ int change = event.width - (customWidth != -1 ? customWidth : contentWidth);
+ if (event.width != contentWidth || customWidth != -1) customWidth = event.width;
+ if (change != 0) { /* scrollbar may be affected since no columns */
+ parent.updateHorizontalBar (contentX + event.width, change);
+ // TODO what if clip is too small now?
+ }
+ }
+ }
+
+ /* if this cell is completely to the right of the client area then there's no need to paint it */
+ Rectangle clientArea = parent.clientArea;
+ if (clientArea.x + clientArea.width < x) return false;
+
+ Rectangle cellBounds = getCellBounds (columnIndex);
+ if (parent.linesVisible) {
+ cellBounds.y++;
+ cellBounds.height--;
+ }
+ int cellRightX = 0;
+ if (column != null) {
+ cellRightX = column.getX () + column.width;
+ } else {
+ cellRightX = cellBounds.x + cellBounds.width;
+ }
+
+ /* restrict the clipping region to the cell */
+ gc.setClipping (x, cellBounds.y, clientArea.width - x, cellBounds.height);
+
+ int y = parent.getItemY (this);
+ int itemHeight = parent.itemHeight;
+
+ /* draw the parent background color/image of this cell */
+ if (column == null) {
+ parent.drawBackground (gc, 0, y, clientArea.width, itemHeight);
+ } else {
+ int fillWidth = cellBounds.width;
+ if (parent.linesVisible) fillWidth--;
+ parent.drawBackground (gc, cellBounds.x, cellBounds.y, fillWidth, cellBounds.height);
+ }
+
+ boolean isSelected = isSelected ();
+ boolean isFocusItem = parent.focusItem == this && parent.isFocusControl ();
+ boolean drawBackground = true;
+ boolean drawForeground = true;
+ boolean drawSelection = isSelected;
+ boolean drawFocus = isFocusItem;
+ if (parent.hooks (SWT.EraseItem)) {
+ drawBackground = background != null || (cellBackgrounds != null && cellBackgrounds [columnIndex] != null);
+ gc.setFont (getFont (columnIndex, false));
+ if (isSelected && (columnIndex == 0 || (parent.style & SWT.FULL_SELECTION) != 0)) {
+ gc.setForeground (display.getSystemColor (SWT.COLOR_LIST_SELECTION_TEXT));
+ gc.setBackground (display.getSystemColor (SWT.COLOR_LIST_SELECTION));
+ } else {
+ gc.setForeground (getForeground (columnIndex));
+ gc.setBackground (getBackground (columnIndex));
+ }
+ Event event = new Event ();
+ event.item = this;
+ event.gc = gc;
+ event.index = columnIndex;
+ event.doit = true;
+ event.detail = SWT.FOREGROUND;
+ if (drawBackground) event.detail |= SWT.BACKGROUND;
+ if (isSelected) event.detail |= SWT.SELECTED;
+ if (isFocusItem) event.detail |= SWT.FOCUSED;
+ event.x = cellBounds.x;
+ event.y = cellBounds.y;
+ event.width = cellBounds.width;
+ event.height = cellBounds.height;
+ gc.setClipping (cellBounds);
+ parent.sendEvent (SWT.EraseItem, event);
+ event.gc = null;
+ if (gc.isDisposed ()) return false;
+ gc.setAlpha (oldAlpha);
+ gc.setAntialias (oldAntialias);
+ gc.setBackgroundPattern (oldBackgroundPattern);
+ gc.setClipping (cellBounds);
+ gc.setForegroundPattern (oldForegroundPattern);
+ gc.setInterpolation (oldInterpolation);
+ gc.setTextAntialias (oldTextAntialias);
+ gc.setAdvanced (oldAdvanced);
+ if (isDisposed ()) return false;
+ if (!event.doit) {
+ drawBackground = drawForeground = drawSelection = drawFocus = false;
+ } else {
+ drawBackground = drawBackground && (event.detail & SWT.BACKGROUND) != 0;
+ drawForeground = (event.detail & SWT.FOREGROUND) != 0;
+ drawSelection = isSelected && (event.detail & SWT.SELECTED) != 0;
+ drawFocus = isFocusItem && (event.detail & SWT.FOCUSED) != 0;
+ }
+ }
+
+ /* draw the cell's set background if appropriate */
+ if (drawBackground) {
+ gc.setBackground (getBackground (columnIndex));
+ if (columnIndex == 0 && (column == null || column.getOrderIndex () == 0)) {
+ Rectangle focusBounds = getFocusBounds ();
+ int fillWidth = 0;
+ if (column == null) {
+ fillWidth = focusBounds.width;
+ } else {
+ fillWidth = column.width - focusBounds.x;
+ if (parent.linesVisible) fillWidth--;
+ }
+ gc.fillRectangle (focusBounds.x, focusBounds.y, fillWidth, focusBounds.height);
+ } else {
+ int fillWidth = cellBounds.width;
+ gc.fillRectangle (cellBounds.x, cellBounds.y, fillWidth, cellBounds.height);
+ }
+ }
+
+ /* draw the selection bar if the receiver is selected */
+ if (drawSelection && (columnIndex == 0 || (parent.style & SWT.FULL_SELECTION) != 0)) {
+ if (parent.hasFocus () || (parent.style & SWT.HIDE_SELECTION) == 0) {
+ gc.setBackground (display.getSystemColor (SWT.COLOR_LIST_SELECTION));
+ if (columnIndex == 0) {
+ Rectangle focusBounds = getFocusBounds ();
+ int startX, fillWidth;
+ if (column == null || column.getOrderIndex () == 0 || (parent.style & SWT.FULL_SELECTION) == 0) {
+ startX = focusBounds.x + 1; /* space for left bound of focus rect */
+ } else {
+ startX = column.getX ();
+ }
+ if (column == null) {
+ fillWidth = focusBounds.width - 2;
+ } else {
+ fillWidth = column.getX () + column.width - startX;
+ if (column.getOrderIndex () == parent.columns.length - 1 || (parent.style & SWT.FULL_SELECTION) == 0) {
+ fillWidth -= 2; /* space for right bound of focus rect */
+ }
+ }
+ if (fillWidth > 0) {
+ gc.fillRectangle (startX, focusBounds.y + 1, fillWidth, focusBounds.height - 2);
+ }
+ } else {
+ int startX = column.getX ();
+ int fillWidth = column.width;
+ if (column.getOrderIndex () == 0) {
+ startX += 1; /* space for left bound of focus rect */
+ fillWidth -= 1;
+ }
+ if (column.getOrderIndex () == parent.columns.length - 1) {
+ fillWidth -= 2; /* space for right bound of focus rect */
+ }
+ if (fillWidth > 0) {
+ gc.fillRectangle (
+ column.getX (),
+ cellBounds.y + 1,
+ fillWidth,
+ cellBounds.height - 2);
+ }
+ }
+ }
+ }
+
+ if (backgroundOnly) return false;
+
+ /* Draw checkbox if drawing column 0 and parent has style SWT.CHECK */
+ if (columnIndex == 0 && (parent.style & SWT.CHECK) != 0) {
+ Image baseImage = grayed ? parent.getGrayUncheckedImage () : parent.getUncheckedImage ();
+ Rectangle checkboxBounds = getCheckboxBounds ();
+ gc.drawImage (baseImage, checkboxBounds.x, checkboxBounds.y);
+ /* Draw checkmark if item is checked */
+ if (checked) {
+ Image checkmarkImage = parent.getCheckmarkImage ();
+ Rectangle checkmarkBounds = checkmarkImage.getBounds ();
+ int xInset = (checkboxBounds.width - checkmarkBounds.width) / 2;
+ int yInset = (checkboxBounds.height - checkmarkBounds.height) / 2;
+ gc.drawImage (checkmarkImage, checkboxBounds.x + xInset, checkboxBounds.y + yInset);
+ }
+ }
+
+ if (drawForeground) {
+ Image image = getImage (columnIndex, false);
+ String text = getDisplayText (columnIndex);
+ Rectangle imageArea = getImageBounds (columnIndex);
+ int startX = imageArea.x;
+
+ /* while painting the cell's content restrict the clipping region */
+ int padding = parent.getCellPadding ();
+ gc.setClipping (
+ startX,
+ cellBounds.y + padding - (parent.linesVisible ? 1 : 0),
+ cellRightX - startX - padding,
+ cellBounds.height - 2 * (padding - (parent.linesVisible ? 1 : 0)));
+
+ /* draw the image */
+ if (image != null) {
+ Rectangle imageBounds = image.getBounds ();
+ gc.drawImage (
+ image,
+ 0, 0, /* source x, y */
+ imageBounds.width, imageBounds.height, /* source width, height */
+ imageArea.x, imageArea.y, /* dest x, y */
+ imageArea.width, imageArea.height); /* dest width, height */
+ }
+
+ /* draw the text */
+ if (text.length () > 0) {
+ gc.setFont (getFont (columnIndex, false));
+ int fontHeight = getFontHeight (columnIndex);
+ if (drawSelection && (columnIndex == 0 || (parent.style & SWT.FULL_SELECTION) != 0)) {
+ if (parent.hasFocus () || (parent.style & SWT.HIDE_SELECTION) == 0) {
+ gc.setForeground (display.getSystemColor (SWT.COLOR_LIST_SELECTION_TEXT));
+ }
+ } else {
+ if (!isSelected || drawSelection) {
+ gc.setForeground (getForeground (columnIndex));
+ }
+ }
+ x = getTextX (columnIndex) + MARGIN_TEXT;
+ gc.drawString (text, x, y + (itemHeight - fontHeight) / 2, true);
+ }
+ }
+
+ if (parent.hooks (SWT.PaintItem)) {
+ int contentWidth = getContentWidth (columnIndex);
+ int contentX = getContentX (columnIndex);
+ gc.setFont (getFont (columnIndex, false));
+ if (isSelected && (columnIndex == 0 || (parent.style & SWT.FULL_SELECTION) != 0)) {
+ gc.setForeground (display.getSystemColor (SWT.COLOR_LIST_SELECTION_TEXT));
+ gc.setBackground (display.getSystemColor (SWT.COLOR_LIST_SELECTION));
+ } else {
+ gc.setForeground (getForeground (columnIndex));
+ gc.setBackground (getBackground (columnIndex));
+ }
+ Event event = new Event ();
+ event.item = this;
+ event.gc = gc;
+ event.index = columnIndex;
+ if (isSelected) event.detail |= SWT.SELECTED;
+ if (drawFocus) event.detail |= SWT.FOCUSED;
+ event.x = contentX;
+ event.y = cellBounds.y;
+ event.width = contentWidth;
+ event.height = cellBounds.height;
+ gc.setClipping (cellBounds);
+ parent.sendEvent (SWT.PaintItem, event);
+ event.gc = null;
+ if (gc.isDisposed ()) return false;
+ gc.setAlpha (oldAlpha);
+ gc.setAntialias (oldAntialias);
+ gc.setBackgroundPattern (oldBackgroundPattern);
+ gc.setClipping (cellBounds);
+ gc.setForegroundPattern (oldForegroundPattern);
+ gc.setInterpolation (oldInterpolation);
+ gc.setTextAntialias (oldTextAntialias);
+ gc.setAdvanced (oldAdvanced);
+ drawFocus = isFocusItem && (event.detail & SWT.FOCUSED) != 0;
+ }
+
+ return isFocusItem && !drawFocus;
+}
+/*
+ * Redraw part of the receiver. If either EraseItem or PaintItem is hooked then
+ * only full cells should be damaged, so adjust accordingly. If neither of these
+ * events are hooked then the exact bounds given for damaging can be used.
+ */
+void redraw (int x, int y, int width, int height, int columnIndex) {
+ if (!parent.hooks (SWT.EraseItem) && !parent.hooks (SWT.PaintItem)) {
+ parent.redraw (x, y, width, height, false);
+ return;
+ }
+ Rectangle cellBounds = getCellBounds (columnIndex);
+ parent.redraw (cellBounds.x, cellBounds.y, cellBounds.width, cellBounds.height, false);
+}
+void redrawItem () {
+ parent.redraw (0, parent.getItemY (this), parent.clientArea.width, parent.itemHeight, false);
+}
+/*
+ * Updates internal structures in the receiver and its child items to handle the removal of a column.
+ */
+void removeColumn (TableColumn column, int index) {
+ int columnCount = parent.columns.length;
+
+ if (columnCount == 0) {
+ /* reverts to normal table when last column disposed */
+ cellBackgrounds = cellForegrounds = null;
+ displayTexts = null;
+ cellFonts = null;
+ fontHeights = null;
+ GC gc = new GC (parent);
+ computeTextWidths (gc);
+ gc.dispose ();
+ return;
+ }
+
+ String[] newTexts = new String [columnCount];
+ System.arraycopy (texts, 0, newTexts, 0, index);
+ System.arraycopy (texts, index + 1, newTexts, index, columnCount - index);
+ texts = newTexts;
+
+ Image[] newImages = new Image [columnCount];
+ System.arraycopy (images, 0, newImages, 0, index);
+ System.arraycopy (images, index + 1, newImages, index, columnCount - index);
+ images = newImages;
+
+ int[] newTextWidths = new int [columnCount];
+ System.arraycopy (textWidths, 0, newTextWidths, 0, index);
+ System.arraycopy (textWidths, index + 1, newTextWidths, index, columnCount - index);
+ textWidths = newTextWidths;
+
+ String[] newDisplayTexts = new String [columnCount];
+ System.arraycopy (displayTexts, 0, newDisplayTexts, 0, index);
+ System.arraycopy (displayTexts, index + 1, newDisplayTexts, index, columnCount - index);
+ displayTexts = newDisplayTexts;
+
+ if (cellBackgrounds != null) {
+ Color[] newCellBackgrounds = new Color [columnCount];
+ System.arraycopy (cellBackgrounds, 0, newCellBackgrounds, 0, index);
+ System.arraycopy (cellBackgrounds, index + 1, newCellBackgrounds, index, columnCount - index);
+ cellBackgrounds = newCellBackgrounds;
+ }
+ if (cellForegrounds != null) {
+ Color[] newCellForegrounds = new Color [columnCount];
+ System.arraycopy (cellForegrounds, 0, newCellForegrounds, 0, index);
+ System.arraycopy (cellForegrounds, index + 1, newCellForegrounds, index, columnCount - index);
+ cellForegrounds = newCellForegrounds;
+ }
+ if (cellFonts != null) {
+ Font[] newCellFonts = new Font [columnCount];
+ System.arraycopy (cellFonts, 0, newCellFonts, 0, index);
+ System.arraycopy (cellFonts, index + 1, newCellFonts, index, columnCount - index);
+ cellFonts = newCellFonts;
+
+ int[] newFontHeights = new int [columnCount];
+ System.arraycopy (fontHeights, 0, newFontHeights, 0, index);
+ System.arraycopy (fontHeights, index + 1, newFontHeights, index, columnCount - index);
+ fontHeights = newFontHeights;
+ }
+
+ if (index == 0) {
+ text = texts [0] != null ? texts [0] : ""; //$NON-NLS-1$
+ texts [0] = null;
+ image = images [0];
+ images [0] = null;
+ /*
+ * The new first column may not have as much width available to it as it did when it was
+ * the second column if checkboxes are being shown, so recompute its displayText if needed.
+ */
+ if ((parent.style & SWT.CHECK) != 0) {
+ GC gc = new GC (parent);
+ gc.setFont (getFont (0, false));
+ computeDisplayText (0, gc);
+ gc.dispose ();
+ }
+ }
+ if (columnCount < 2) {
+ texts = null;
+ images = null;
+ }
+}
+/**
+ * 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>
+ *
+ * @since 2.0
+ */
+public void setBackground (Color color) {
+ checkWidget ();
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ Color oldColor = background;
+ if (oldColor == color) return;
+ background = color;
+ if (oldColor != null && oldColor.equals (color)) return;
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ redrawItem ();
+}
+/**
+ * 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>
+ *
+ * @since 3.0
+ */
+public void setBackground (int columnIndex, Color color) {
+ checkWidget ();
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int validColumnCount = Math.max (1, parent.columns.length);
+ if (!(0 <= columnIndex && columnIndex < validColumnCount)) return;
+ if (cellBackgrounds == null) {
+ if (color == null) return;
+ cellBackgrounds = new Color [validColumnCount];
+ }
+ Color oldColor = cellBackgrounds [columnIndex];
+ if (oldColor == color) return;
+ cellBackgrounds [columnIndex] = color;
+ if (oldColor != null && oldColor.equals (color)) return;
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+
+ if (isInViewport ()) {
+ Rectangle bounds = getCellBounds (columnIndex);
+ parent.redraw (bounds.x, bounds.y, bounds.width, bounds.height, false);
+ }
+}
+/**
+ * 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 value) {
+ checkWidget ();
+ if ((parent.getStyle () & SWT.CHECK) == 0) return;
+ if (checked == value) return;
+ checked = value;
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+
+ if (isInViewport ()) {
+ if (parent.hooks (SWT.EraseItem) || parent.hooks (SWT.PaintItem)) {
+ redrawItem ();
+ } else {
+ Rectangle bounds = getCheckboxBounds ();
+ parent.redraw (bounds.x, bounds.y, bounds.width, bounds.height, false);
+ }
+ }
+}
+/**
+ * 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>
+ *
+ * @since 3.0
+ */
+public void setFont (Font font) {
+ checkWidget ();
+ if (font != null && font.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ Font oldFont = this.font;
+ if (oldFont == font) return;
+ this.font = font;
+ if (oldFont != null && oldFont.equals (font)) return;
+
+ Rectangle bounds = getBounds (false);
+ int oldRightX = bounds.x + bounds.width;
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+
+ /* recompute cached values for string measurements */
+ GC gc = new GC (parent);
+ gc.setFont (getFont (false));
+ fontHeight = gc.getFontMetrics ().getHeight ();
+ computeDisplayTexts (gc);
+ computeTextWidths (gc);
+ gc.dispose ();
+
+ /* horizontal bar could be affected if table has no columns */
+ if (parent.columns.length == 0) {
+ bounds = getBounds (false);
+ int newRightX = bounds.x + bounds.width;
+ parent.updateHorizontalBar (newRightX, newRightX - oldRightX);
+ }
+ redrawItem ();
+}
+/**
+ * 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>
+ *
+ * @since 3.0
+ */
+public void setFont (int columnIndex, Font font) {
+ checkWidget ();
+ if (font != null && font.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ int validColumnCount = Math.max (1, parent.columns.length);
+ if (!(0 <= columnIndex && columnIndex < validColumnCount)) return;
+ if (cellFonts == null) {
+ if (font == null) return;
+ cellFonts = new Font [validColumnCount];
+ }
+ Font oldFont = cellFonts [columnIndex];
+ if (oldFont == font) return;
+ cellFonts [columnIndex] = font;
+ if (oldFont != null && oldFont.equals (font)) return;
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+
+ /* recompute cached values for string measurements */
+ GC gc = new GC (parent);
+ gc.setFont (getFont (columnIndex, false));
+ if (fontHeights == null) fontHeights = new int [validColumnCount];
+ fontHeights [columnIndex] = gc.getFontMetrics ().getHeight ();
+ computeDisplayText (columnIndex, gc);
+ gc.dispose ();
+
+ if (isInViewport ()) {
+ Rectangle bounds = getCellBounds (columnIndex);
+ parent.redraw (bounds.x, bounds.y, bounds.width, bounds.height, false);
+ }
+}
+/**
+ * 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>
+ *
+ * @since 2.0
+ */
+public void setForeground (Color color) {
+ checkWidget ();
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ Color oldColor = foreground;
+ if (oldColor == color) return;
+ foreground = color;
+ if (oldColor != null && oldColor.equals (color)) return;
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ redrawItem ();
+}
+/**
+ * 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>
+ *
+ * @since 3.0
+ */
+public void setForeground (int columnIndex, Color color) {
+ checkWidget ();
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int validColumnCount = Math.max (1, parent.columns.length);
+ if (!(0 <= columnIndex && columnIndex < validColumnCount)) return;
+ if (cellForegrounds == null) {
+ if (color == null) return;
+ cellForegrounds = new Color [validColumnCount];
+ }
+ Color oldColor = cellForegrounds [columnIndex];
+ if (oldColor == color) return;
+ cellForegrounds [columnIndex] = color;
+ if (oldColor != null && oldColor.equals (color)) return;
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+
+ if (isInViewport ()) {
+ redraw (
+ getTextX (columnIndex),
+ parent.getItemY (this),
+ textWidths [columnIndex] + 2 * MARGIN_TEXT,
+ parent.itemHeight,
+ columnIndex);
+ }
+}
+/**
+ * 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 value) {
+ checkWidget ();
+ if ((parent.getStyle () & SWT.CHECK) == 0) return;
+ if (grayed == value) return;
+ grayed = value;
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+
+ if (isInViewport ()) {
+ Rectangle bounds = getCheckboxBounds ();
+ parent.redraw (bounds.x, bounds.y, bounds.width, bounds.height, false);
+ }
+}
+public void setImage (Image value) {
+ checkWidget ();
+ setImage (0, value);
+}
+/**
+ * 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[] value) {
+ checkWidget ();
+ if (value == null) error (SWT.ERROR_NULL_ARGUMENT);
+
+ // TODO make a smarter implementation of this
+ for (int i = 0; i < value.length; i++) {
+ if (value [i] != null) setImage (i, value [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 columnIndex, Image value) {
+ checkWidget ();
+ if (value != null && value.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+
+ TableColumn[] columns = parent.columns;
+ int validColumnCount = Math.max (1, columns.length);
+ if (!(0 <= columnIndex && columnIndex < validColumnCount)) return;
+ Image image = getImage (columnIndex, false);
+ if (value == image) return;
+ if (value != null && value.equals (image)) return;
+ if (columnIndex == 0) {
+ super.setImage (value);
+ } else {
+ images [columnIndex] = value;
+ }
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+
+ /*
+ * An image width change may affect the space available for the item text, so
+ * recompute the displayText if there are columns.
+ */
+ if (columns.length > 0) {
+ GC gc = new GC (parent);
+ gc.setFont (getFont (columnIndex, false));
+ computeDisplayText (columnIndex, gc);
+ gc.dispose ();
+ }
+
+ if (value == null) {
+ redrawItem (); // TODO why the whole item?
+ return;
+ }
+
+ /*
+ * If this is the first image being put into the table then its item height
+ * may be adjusted, in which case a full redraw is needed.
+ */
+ if (parent.imageHeight == 0) {
+ int oldItemHeight = parent.itemHeight;
+ parent.setImageHeight (value.getBounds ().height);
+ if (oldItemHeight != parent.itemHeight) {
+ if (columnIndex == 0) {
+ parent.col0ImageWidth = value.getBounds ().width;
+ if (columns.length > 0) {
+ /*
+ * All column 0 cells will now have less room available for their texts,
+ * so all items must now recompute their column 0 displayTexts.
+ */
+ GC gc = new GC (parent);
+ TableItem[] rootItems = parent.items;
+ for (int i = 0; i < parent.itemsCount; i++) {
+ rootItems [i].updateColumnWidth (columns [0], gc);
+ }
+ gc.dispose ();
+ }
+ }
+ parent.redraw ();
+ return;
+ }
+ }
+
+ /*
+ * If this is the first image being put into column 0 then all cells
+ * in the column should also indent accordingly.
+ */
+ if (columnIndex == 0 && parent.col0ImageWidth == 0) {
+ parent.col0ImageWidth = value.getBounds ().width;
+ /* redraw the column */
+ if (columns.length == 0) {
+ parent.redraw ();
+ } else {
+ /*
+ * All column 0 cells will now have less room available for their texts,
+ * so all items must now recompute their column 0 displayTexts.
+ */
+ GC gc = new GC (parent);
+ TableItem[] rootItems = parent.items;
+ for (int i = 0; i < parent.itemsCount; i++) {
+ rootItems [i].updateColumnWidth (columns [0], gc);
+ }
+ gc.dispose ();
+ parent.redraw (
+ columns [0].getX (), 0,
+ columns [0].width,
+ parent.clientArea.height,
+ false);
+ }
+ return;
+ }
+ redrawItem (); // TODO why the whole item?
+}
+/**
+ * Sets the indent of the first column's image, expressed in terms of the image's width.
+ *
+ * @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>
+ *
+ * @deprecated this functionality is not supported on most platforms
+ */
+public void setImageIndent (int indent) {
+ checkWidget();
+ if (indent < 0) return;
+ if (imageIndent == indent) return;
+ imageIndent = indent;
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+}
+/**
+ * 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 columnIndex, String value) {
+ checkWidget ();
+ if (value == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int validColumnCount = Math.max (1, parent.columns.length);
+ if (!(0 <= columnIndex && columnIndex < validColumnCount)) return;
+ if (value.equals (getText (columnIndex, false))) return;
+ if (columnIndex == 0) {
+ super.setText (value);
+ } else {
+ texts [columnIndex] = value;
+ }
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+
+ int oldWidth = textWidths [columnIndex];
+ GC gc = new GC (parent);
+ gc.setFont (getFont (columnIndex, false));
+ computeDisplayText (columnIndex, gc);
+ gc.dispose ();
+
+ if (parent.columns.length == 0) {
+ Rectangle bounds = getBounds (false);
+ int rightX = bounds.x + bounds.width;
+ parent.updateHorizontalBar (rightX, textWidths [columnIndex] - oldWidth);
+ }
+ if (isInViewport ()) {
+ redraw (
+ getTextX (columnIndex),
+ parent.getItemY (this),
+ Math.max (oldWidth, textWidths [columnIndex]) + 2 * MARGIN_TEXT,
+ parent.itemHeight,
+ columnIndex);
+ }
+}
+public void setText (String value) {
+ checkWidget ();
+ Rectangle bounds = getBounds (false);
+ int oldRightX = bounds.x + bounds.width;
+ setText (0, value);
+ /* horizontal bar could be affected if table has no columns */
+ if (parent.columns.length == 0) {
+ bounds = getBounds (false);
+ int newRightX = bounds.x + bounds.width;
+ parent.updateHorizontalBar (newRightX, newRightX - oldRightX);
+ }
+}
+/**
+ * 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[] value) {
+ checkWidget ();
+ if (value == null) error (SWT.ERROR_NULL_ARGUMENT);
+ Rectangle bounds = getBounds (false);
+ int oldRightX = bounds.x + bounds.width;
+ // TODO make a smarter implementation of this
+ for (int i = 0; i < value.length; i++) {
+ if (value [i] != null) setText (i, value [i]);
+ }
+ /* horizontal bar could be affected if table has no columns */
+ if (parent.columns.length == 0) {
+ bounds = getBounds (false);
+ int newRightX = bounds.x + bounds.width;
+ parent.updateHorizontalBar (newRightX, newRightX - oldRightX);
+ }
+}
+/*
+ * Perform any internal changes necessary to reflect a changed column width.
+ */
+void updateColumnWidth (TableColumn column, GC gc) {
+ int columnIndex = column.getIndex ();
+ gc.setFont (getFont (columnIndex, false));
+ String oldDisplayText = displayTexts [columnIndex];
+ computeDisplayText (columnIndex, gc);
+
+ /* the cell must be damaged if there is custom drawing being done or if the alignment is not LEFT */
+ if (isInViewport ()) {
+ boolean columnIsLeft = (column.style & SWT.LEFT) != 0;
+ if (!columnIsLeft || parent.hooks (SWT.EraseItem) || parent.hooks (SWT.PaintItem)) {
+ Rectangle cellBounds = getCellBounds (columnIndex);
+ parent.redraw (cellBounds.x, cellBounds.y, cellBounds.width, cellBounds.height, false);
+ return;
+ }
+ /* if the display text has changed then the cell text must be damaged in order to repaint */
+ if (oldDisplayText == null || !oldDisplayText.equals (displayTexts [columnIndex])) {
+ Rectangle cellBounds = getCellBounds (columnIndex);
+ int textX = getTextX (columnIndex);
+ parent.redraw (textX, cellBounds.y, cellBounds.x + cellBounds.width - textX, cellBounds.height, false);
+ }
+ }
+}
+/*
+ * The parent's font has changed, so if this font was being used by the receiver then
+ * recompute its cached text sizes using the gc argument.
+ */
+void updateFont (GC gc) {
+ if (font == null) { /* receiver is using the Table's font */
+ computeDisplayTexts (gc);
+ computeTextWidths (gc);
+ }
+}
+}

Back to the top