1 /*******************************************************************************
2 * Copyright (c) 2000, 2015 IBM Corporation and others.
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
9 * SPDX-License-Identifier: EPL-2.0
12 * IBM Corporation - initial API and implementation
13 *******************************************************************************/
14 package org.eclipse.swt.widgets;
17 import org.eclipse.swt.*;
18 import org.eclipse.swt.graphics.*;
19 import org.eclipse.swt.internal.*;
20 import org.eclipse.swt.internal.win32.*;
23 * Instances of this class represent a selectable user interface object
24 * that represents an item in a table.
26 * <dt><b>Styles:</b></dt>
28 * <dt><b>Events:</b></dt>
32 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
35 * @see <a href="http://www.eclipse.org/swt/snippets/#table">Table, TableItem, TableColumn snippets</a>
36 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
37 * @noextend This class is not intended to be subclassed by clients.
39 public class TableItem extends Item {
45 boolean checked, grayed, cached;
46 int imageIndent, background = -1, foreground = -1;
47 int [] cellBackground, cellForeground;
50 * Constructs a new instance of this class given its parent
51 * (which must be a <code>Table</code>) and a style value
52 * describing its behavior and appearance. The item is added
53 * to the end of the items maintained by its parent.
55 * The style value is either one of the style constants defined in
56 * class <code>SWT</code> which is applicable to instances of this
57 * class, or must be built by <em>bitwise OR</em>'ing together
58 * (that is, using the <code>int</code> "|" operator) two or more
59 * of those <code>SWT</code> style constants. The class description
60 * lists the style constants that are applicable to the class.
61 * Style bits are also inherited from superclasses.
64 * @param parent a composite control which will be the parent of the new instance (cannot be null)
65 * @param style the style of control to construct
67 * @exception IllegalArgumentException <ul>
68 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
70 * @exception SWTException <ul>
71 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
72 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
76 * @see Widget#checkSubclass
77 * @see Widget#getStyle
79 public TableItem (Table parent, int style) {
80 this (parent, style, checkNull (parent).getItemCount (), true);
84 * Constructs a new instance of this class given its parent
85 * (which must be a <code>Table</code>), a style value
86 * describing its behavior and appearance, and the index
87 * at which to place it in the items maintained by its parent.
89 * The style value is either one of the style constants defined in
90 * class <code>SWT</code> which is applicable to instances of this
91 * class, or must be built by <em>bitwise OR</em>'ing together
92 * (that is, using the <code>int</code> "|" operator) two or more
93 * of those <code>SWT</code> style constants. The class description
94 * lists the style constants that are applicable to the class.
95 * Style bits are also inherited from superclasses.
98 * @param parent a composite control which will be the parent of the new instance (cannot be null)
99 * @param style the style of control to construct
100 * @param index the zero-relative index to store the receiver in its parent
102 * @exception IllegalArgumentException <ul>
103 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
104 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
106 * @exception SWTException <ul>
107 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
108 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
112 * @see Widget#checkSubclass
113 * @see Widget#getStyle
115 public TableItem (Table parent, int style, int index) {
116 this (parent, style, index, true);
119 TableItem (Table parent, int style, int index, boolean create) {
120 super (parent, style);
121 this.parent = parent;
122 if (create) parent.createItem (this, index);
125 static Table checkNull (Table control) {
126 if (control == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
131 protected void checkSubclass () {
132 if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
141 checked = grayed = false;
143 background = foreground = -1;
145 cellBackground = cellForeground = null;
146 if ((parent.style & SWT.VIRTUAL) != 0) cached = false;
150 void destroyWidget () {
151 parent.destroyItem (this);
155 long fontHandle (int index) {
156 if (cellFont != null && cellFont [index] != null) return cellFont [index].handle;
157 if (font != null) return font.handle;
162 * Returns the receiver's background color.
164 * @return the background color
166 * @exception SWTException <ul>
167 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
168 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
173 public Color getBackground () {
175 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
176 if (background == -1) return parent.getBackground ();
177 return Color.win32_new (display, background);
181 * Returns the background color at the given column index in the receiver.
183 * @param index the column index
184 * @return the background color
186 * @exception SWTException <ul>
187 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
188 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
193 public Color getBackground (int index) {
195 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
196 int count = Math.max (1, parent.getColumnCount ());
197 if (0 > index || index > count - 1) return getBackground ();
198 int pixel = cellBackground != null ? cellBackground [index] : -1;
199 return pixel == -1 ? getBackground () : Color.win32_new (display, pixel);
203 * Returns a rectangle describing the size and location of the receiver's
204 * text relative to its parent.
206 * @return the bounding rectangle of the receiver's text
208 * @exception SWTException <ul>
209 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
210 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
215 public Rectangle getBounds () {
217 return DPIUtil.autoScaleDown(getBoundsInPixels());
220 Rectangle getBoundsInPixels () {
221 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
222 int itemIndex = parent.indexOf (this);
223 if (itemIndex == -1) return new Rectangle (0, 0, 0, 0);
224 RECT rect = getBounds (itemIndex, 0, true, false, false);
225 int width = rect.right - rect.left, height = rect.bottom - rect.top;
226 return new Rectangle (rect.left, rect.top, width, height);
230 * Returns a rectangle describing the receiver's size and location
231 * relative to its parent at a column in the table.
233 * @param index the index that specifies the column
234 * @return the receiver's bounding column rectangle
236 * @exception SWTException <ul>
237 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
238 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
241 public Rectangle getBounds (int index) {
243 return DPIUtil.autoScaleDown(getBoundsInPixels(index));
246 Rectangle getBoundsInPixels (int index) {
247 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
248 int itemIndex = parent.indexOf (this);
249 if (itemIndex == -1) return new Rectangle (0, 0, 0, 0);
250 RECT rect = getBounds (itemIndex, index, true, true, true);
251 int width = rect.right - rect.left, height = rect.bottom - rect.top;
252 return new Rectangle (rect.left, rect.top, width, height);
255 RECT getBounds (int row, int column, boolean getText, boolean getImage, boolean fullText) {
256 return getBounds (row, column, getText, getImage, fullText, false, 0);
259 RECT getBounds (int row, int column, boolean getText, boolean getImage, boolean fullText, boolean fullImage, long hDC) {
260 if (!getText && !getImage) return new RECT ();
261 int columnCount = parent.getColumnCount ();
262 if (!(0 <= column && column < Math.max (1, columnCount))) {
265 if (parent.fixScrollWidth) parent.setScrollWidth (null, true);
266 RECT rect = new RECT ();
267 long hwnd = parent.handle;
268 int bits = (int)OS.SendMessage (hwnd, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
269 if (column == 0 && (bits & OS.LVS_EX_FULLROWSELECT) == 0) {
270 if (parent.explorerTheme) {
271 rect.left = OS.LVIR_ICON;
272 parent.ignoreCustomDraw = true;
273 long code = OS.SendMessage (hwnd, OS. LVM_GETITEMRECT, row, rect);
274 parent.ignoreCustomDraw = false;
275 if (code == 0) return new RECT ();
278 long hFont = fontHandle (column);
279 if (hFont == -1 && hDC == 0) {
280 TCHAR buffer = new TCHAR (parent.getCodePage (), text, true);
281 width = (int)OS.SendMessage (hwnd, OS.LVM_GETSTRINGWIDTH, 0, buffer);
283 char [] buffer = text.toCharArray ();
284 long textDC = hDC != 0 ? hDC : OS.GetDC (hwnd), oldFont = -1;
286 if (hFont == -1) hFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
287 oldFont = OS.SelectObject (textDC, hFont);
289 RECT textRect = new RECT ();
290 int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_CALCRECT;
291 OS.DrawText (textDC, buffer, buffer.length, textRect, flags);
292 width = textRect.right - textRect.left;
294 if (oldFont != -1) OS.SelectObject (textDC, oldFont);
295 OS.ReleaseDC (hwnd, textDC);
298 if (!getImage) rect.left = rect.right;
299 rect.right += width + Table.INSET * 2;
303 rect.left = OS.LVIR_SELECTBOUNDS;
304 parent.ignoreCustomDraw = true;
305 long code = OS.SendMessage (hwnd, OS.LVM_GETITEMRECT, row, rect);
306 parent.ignoreCustomDraw = false;
307 if (code == 0) return new RECT ();
309 RECT iconRect = new RECT ();
310 iconRect.left = OS.LVIR_ICON;
311 parent.ignoreCustomDraw = true;
312 code = OS.SendMessage (hwnd, OS. LVM_GETITEMRECT, row, iconRect);
313 parent.ignoreCustomDraw = false;
314 if (code != 0) rect.left = iconRect.right;
317 rect.left = OS.LVIR_ICON;
318 parent.ignoreCustomDraw = true;
319 long code = OS.SendMessage (hwnd, OS.LVM_GETITEMRECT, row, rect);
320 parent.ignoreCustomDraw = false;
321 if (code == 0) return new RECT ();
324 if (fullText || fullImage) {
325 RECT headerRect = new RECT ();
326 long hwndHeader = OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
327 OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, 0, headerRect);
328 OS.MapWindowPoints (hwndHeader, hwnd, headerRect, 2);
329 if (getText && fullText) rect.right = headerRect.right;
330 if (getImage && fullImage) rect.left = headerRect.left;
334 * Feature in Windows. LVM_GETSUBITEMRECT returns an image width
335 * even when the subitem does not contain an image. The fix is to
336 * test for this case and adjust the rectangle to represent the area
337 * the table is actually drawing.
339 boolean hasImage = (column == 0 && image != null) || (images != null && images [column] != null);
341 if (fullText || fullImage || hDC == 0) {
343 * Bug in Windows. Despite the fact that the documentation states
344 * that LVIR_BOUNDS and LVIR_LABEL are identical when used with
345 * LVM_GETSUBITEMRECT, LVIR_BOUNDS can return a zero height. The
346 * fix is to use LVIR_LABEL.
348 rect.left = getText ? OS.LVIR_LABEL : OS.LVIR_ICON;
349 parent.ignoreCustomDraw = true;
350 long code = OS.SendMessage (hwnd, OS. LVM_GETSUBITEMRECT, row, rect);
351 parent.ignoreCustomDraw = false;
352 if (code == 0) return new RECT ();
354 * Feature in Windows. Calling LVM_GETSUBITEMRECT with LVIR_LABEL
355 * and zero for the column number gives the bounds of the first item
356 * without including the bounds of the icon. This is undocumented.
357 * When called with values greater than zero, the icon bounds are
358 * included and this behavior is documented. If the icon is needed
359 * in the bounds of the first item, the fix is to adjust the item
360 * bounds using the icon bounds.
362 if (column == 0 && getText && getImage) {
363 RECT iconRect = new RECT ();
364 iconRect.left = OS.LVIR_ICON;
365 parent.ignoreCustomDraw = true;
366 code = OS.SendMessage (hwnd, OS. LVM_GETSUBITEMRECT, row, iconRect);
367 parent.ignoreCustomDraw = false;
368 if (code != 0) rect.left = iconRect.left;
371 if (column != 0 && getText && !getImage) {
372 RECT iconRect = new RECT ();
373 iconRect.top = column;
374 iconRect.left = OS.LVIR_ICON;
375 if (OS.SendMessage (hwnd, OS. LVM_GETSUBITEMRECT, row, iconRect) != 0) {
376 rect.left = iconRect.right + Table.INSET / 2;
380 if (getImage && !getText) rect.right = rect.left;
382 if (column == 0 && fullImage) {
383 RECT headerRect = new RECT ();
384 long hwndHeader = OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
385 OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, 0, headerRect);
386 OS.MapWindowPoints (hwndHeader, hwnd, headerRect, 2);
387 rect.left = headerRect.left;
390 rect.left = OS.LVIR_ICON;
391 parent.ignoreCustomDraw = true;
392 long code = OS.SendMessage (hwnd, OS. LVM_GETSUBITEMRECT, row, rect);
393 parent.ignoreCustomDraw = false;
394 if (code == 0) return new RECT ();
395 if (!hasImage) rect.right = rect.left;
397 String string = column == 0 ? text : strings != null ? strings [column] : null;
398 if (string != null) {
399 RECT textRect = new RECT ();
400 char [] buffer = string.toCharArray ();
401 int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_CALCRECT;
402 OS.DrawText (hDC, buffer, buffer.length, textRect, flags);
403 rect.right += textRect.right - textRect.left + Table.INSET * 3 + 2;
409 * Bug in Windows. In version 5.80 of COMCTL32.DLL, the top
410 * of the rectangle returned by LVM_GETSUBITEMRECT is off by
411 * the grid width when the grid is visible. The fix is to
412 * move the top of the rectangle up by the grid width.
414 int gridWidth = parent.getLinesVisible () ? Table.GRID_WIDTH : 0;
415 rect.top -= gridWidth;
416 if (column != 0) rect.left += gridWidth;
417 rect.right = Math.max (rect.right, rect.left);
418 rect.top += gridWidth;
419 rect.bottom = Math.max (rect.bottom - gridWidth, rect.top);
424 * Returns <code>true</code> if the receiver is checked,
425 * and false otherwise. When the parent does not have
426 * the <code>CHECK</code> style, return false.
428 * @return the checked state of the checkbox
430 * @exception SWTException <ul>
431 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
432 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
435 public boolean getChecked () {
437 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
438 if ((parent.style & SWT.CHECK) == 0) return false;
443 * Returns the font that the receiver will use to paint textual information for this item.
445 * @return the receiver's font
447 * @exception SWTException <ul>
448 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
449 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
454 public Font getFont () {
456 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
457 return font != null ? font : parent.getFont ();
461 * Returns the font that the receiver will use to paint textual information
462 * for the specified cell in this item.
464 * @param index the column index
465 * @return the receiver's font
467 * @exception SWTException <ul>
468 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
469 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
474 public Font getFont (int index) {
476 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
477 int count = Math.max (1, parent.getColumnCount ());
478 if (0 > index || index > count -1) return getFont ();
479 if (cellFont == null || cellFont [index] == null) return getFont ();
480 return cellFont [index];
484 * Returns the foreground color that the receiver will use to draw.
486 * @return the receiver's foreground color
488 * @exception SWTException <ul>
489 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
490 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
495 public Color getForeground () {
497 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
498 if (foreground == -1) return parent.getForeground ();
499 return Color.win32_new (display, foreground);
504 * Returns the foreground color at the given column index in the receiver.
506 * @param index the column index
507 * @return the foreground color
509 * @exception SWTException <ul>
510 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
511 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
516 public Color getForeground (int index) {
518 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
519 int count = Math.max (1, parent.getColumnCount ());
520 if (0 > index || index > count -1) return getForeground ();
521 int pixel = cellForeground != null ? cellForeground [index] : -1;
522 return pixel == -1 ? getForeground () : Color.win32_new (display, pixel);
526 * Returns <code>true</code> if the receiver is grayed,
527 * and false otherwise. When the parent does not have
528 * the <code>CHECK</code> style, return false.
530 * @return the grayed state of the checkbox
532 * @exception SWTException <ul>
533 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
534 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
537 public boolean getGrayed () {
539 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
540 if ((parent.style & SWT.CHECK) == 0) return false;
545 public Image getImage () {
547 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
548 return super.getImage ();
552 * Returns the image stored at the given column index in the receiver,
553 * or null if the image has not been set or if the column does not exist.
555 * @param index the column index
556 * @return the image stored at the given column index in the receiver
558 * @exception SWTException <ul>
559 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
560 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
563 public Image getImage (int index) {
565 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
566 if (index == 0) return getImage ();
567 if (images != null) {
568 if (0 <= index && index < images.length) return images [index];
574 * Returns a rectangle describing the size and location
575 * relative to its parent of an image at a column in the
576 * table. An empty rectangle is returned if index exceeds
577 * the index of the table's last column.
579 * @param index the index that specifies the column
580 * @return the receiver's bounding image rectangle
582 * @exception SWTException <ul>
583 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
584 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
587 public Rectangle getImageBounds (int index) {
589 return DPIUtil.autoScaleDown(getImageBoundsInPixels(index));
592 Rectangle getImageBoundsInPixels (int index) {
593 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
594 int itemIndex = parent.indexOf (this);
595 if (itemIndex == -1) return new Rectangle (0, 0, 0, 0);
596 RECT rect = getBounds (itemIndex, index, false, true, false);
597 int width = rect.right - rect.left, height = rect.bottom - rect.top;
598 return new Rectangle (rect.left, rect.top, width, height);
602 * Gets the image indent.
606 * @exception SWTException <ul>
607 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
608 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
611 public int getImageIndent () {
613 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
618 String getNameText () {
619 if ((parent.style & SWT.VIRTUAL) != 0) {
620 if (!cached) return "*virtual*"; //$NON-NLS-1$
622 return super.getNameText ();
626 * Returns the receiver's parent, which must be a <code>Table</code>.
628 * @return the receiver's parent
630 * @exception SWTException <ul>
631 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
632 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
635 public Table getParent () {
641 public String getText () {
643 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
644 return super.getText ();
648 * Returns the text stored at the given column index in the receiver,
649 * or empty string if the text has not been set.
651 * @param index the column index
652 * @return the text stored at the given column index in the receiver
654 * @exception SWTException <ul>
655 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
656 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
659 public String getText (int index) {
661 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
662 if (index == 0) return getText ();
663 if (strings != null) {
664 if (0 <= index && index < strings.length) {
665 String string = strings [index];
666 return string != null ? string : "";
673 * Returns a rectangle describing the size and location
674 * relative to its parent of the text at a column in the
675 * table. An empty rectangle is returned if index exceeds
676 * the index of the table's last column.
678 * @param index the index that specifies the column
679 * @return the receiver's bounding text rectangle
681 * @exception SWTException <ul>
682 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
683 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
688 public Rectangle getTextBounds (int index) {
690 return DPIUtil.autoScaleDown(getTextBoundsInPixels(index));
693 Rectangle getTextBoundsInPixels (int index) {
694 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
695 int itemIndex = parent.indexOf (this);
696 if (itemIndex == -1) return new Rectangle (0, 0, 0, 0);
697 RECT rect = getBounds (itemIndex, index, true, false, true);
699 if (index != 0) rect.left += Table.INSET;
700 rect.left = Math.min (rect.left, rect.right);
701 rect.right = rect.right - Table.INSET;
702 int width = Math.max (0, rect.right - rect.left);
703 int height = Math.max (0, rect.bottom - rect.top);
704 return new Rectangle (rect.left, rect.top, width, height);
708 if (parent.currentItem == this || !parent.getDrawing ()) return;
709 long hwnd = parent.handle;
710 if (!OS.IsWindowVisible (hwnd)) return;
711 int index = parent.indexOf (this);
712 if (index == -1) return;
713 OS.SendMessage (hwnd, OS.LVM_REDRAWITEMS, index, index);
716 void redraw (int column, boolean drawText, boolean drawImage) {
717 if (parent.currentItem == this || !parent.getDrawing ()) return;
718 long hwnd = parent.handle;
719 if (!OS.IsWindowVisible (hwnd)) return;
720 int index = parent.indexOf (this);
721 if (index == -1) return;
722 RECT rect = getBounds (index, column, drawText, drawImage, true);
723 OS.InvalidateRect (hwnd, rect, true);
727 void releaseHandle () {
728 super.releaseHandle ();
733 void releaseWidget () {
734 super.releaseWidget ();
738 cellBackground = cellForeground = null;
742 * Sets the receiver's background color to the color specified
743 * by the argument, or to the default system color for the item
744 * if the argument is null.
746 * @param color the new color (or null)
748 * @exception IllegalArgumentException <ul>
749 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
751 * @exception SWTException <ul>
752 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
753 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
758 public void setBackground (Color color) {
760 if (color != null && color.isDisposed ()) {
761 error (SWT.ERROR_INVALID_ARGUMENT);
765 parent.setCustomDraw (true);
766 pixel = color.handle;
768 if (background == pixel) return;
770 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
775 * Sets the background color at the given column index in the receiver
776 * to the color specified by the argument, or to the default system color for the item
777 * if the argument is null.
779 * @param index the column index
780 * @param color the new color (or null)
782 * @exception IllegalArgumentException <ul>
783 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
785 * @exception SWTException <ul>
786 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
787 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
792 public void setBackground (int index, Color color) {
794 if (color != null && color.isDisposed ()) {
795 error (SWT.ERROR_INVALID_ARGUMENT);
797 int count = Math.max (1, parent.getColumnCount ());
798 if (0 > index || index > count - 1) return;
801 parent.setCustomDraw (true);
802 pixel = color.handle;
804 if (cellBackground == null) {
805 cellBackground = new int [count];
806 for (int i = 0; i < count; i++) {
807 cellBackground [i] = -1;
810 if (cellBackground [index] == pixel) return;
811 cellBackground [index] = pixel;
812 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
813 redraw (index, true, true);
817 * Sets the checked state of the checkbox for this item. This state change
818 * only applies if the Table was created with the SWT.CHECK style.
820 * @param checked the new checked state of the checkbox
822 * @exception SWTException <ul>
823 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
824 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
827 public void setChecked (boolean checked) {
829 if ((parent.style & SWT.CHECK) == 0) return;
830 if (this.checked == checked) return;
831 setChecked (checked, false);
834 void setChecked (boolean checked, boolean notify) {
835 this.checked = checked;
836 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
838 Event event = new Event();
840 event.detail = SWT.CHECK;
841 parent.sendSelectionEvent (SWT.Selection, event, false);
847 * Sets the font that the receiver will use to paint textual information
848 * for this item to the font specified by the argument, or to the default font
849 * for that kind of control if the argument is null.
851 * @param font the new font (or null)
853 * @exception IllegalArgumentException <ul>
854 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
856 * @exception SWTException <ul>
857 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
858 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
863 public void setFont (Font font){
865 if (font != null && font.isDisposed ()) {
866 error (SWT.ERROR_INVALID_ARGUMENT);
868 Font oldFont = this.font;
869 if (oldFont == font) return;
871 if (oldFont != null && oldFont.equals (font)) return;
872 if (font != null) parent.setCustomDraw (true);
873 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
875 * Bug in Windows. Despite the fact that every item in the
876 * table always has LPSTR_TEXTCALLBACK, Windows caches the
877 * bounds for the selected items. This means that
878 * when you change the string to be something else, Windows
879 * correctly asks you for the new string but when the item
880 * is selected, the selection draws using the bounds of the
881 * previous item. The fix is to reset LPSTR_TEXTCALLBACK
882 * even though it has not changed, causing Windows to flush
885 if ((parent.style & SWT.VIRTUAL) == 0 && cached) {
886 int itemIndex = parent.indexOf (this);
887 if (itemIndex != -1) {
888 long hwnd = parent.handle;
889 LVITEM lvItem = new LVITEM ();
890 lvItem.mask = OS.LVIF_TEXT;
891 lvItem.iItem = itemIndex;
892 lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
893 OS.SendMessage (hwnd, OS.LVM_SETITEM, 0, lvItem);
897 parent.setScrollWidth (this, false);
902 * Sets the font that the receiver will use to paint textual information
903 * for the specified cell in this item to the font specified by the
904 * argument, or to the default font for that kind of control if the
907 * @param index the column index
908 * @param font the new font (or null)
910 * @exception IllegalArgumentException <ul>
911 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
913 * @exception SWTException <ul>
914 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
915 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
920 public void setFont (int index, Font font) {
922 if (font != null && font.isDisposed ()) {
923 error (SWT.ERROR_INVALID_ARGUMENT);
925 int count = Math.max (1, parent.getColumnCount ());
926 if (0 > index || index > count - 1) return;
927 if (cellFont == null) {
928 if (font == null) return;
929 cellFont = new Font [count];
931 Font oldFont = cellFont [index];
932 if (oldFont == font) return;
933 cellFont [index] = font;
934 if (oldFont != null && oldFont.equals (font)) return;
935 if (font != null) parent.setCustomDraw (true);
936 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
939 * Bug in Windows. Despite the fact that every item in the
940 * table always has LPSTR_TEXTCALLBACK, Windows caches the
941 * bounds for the selected items. This means that
942 * when you change the string to be something else, Windows
943 * correctly asks you for the new string but when the item
944 * is selected, the selection draws using the bounds of the
945 * previous item. The fix is to reset LPSTR_TEXTCALLBACK
946 * even though it has not changed, causing Windows to flush
949 if ((parent.style & SWT.VIRTUAL) == 0 && cached) {
950 int itemIndex = parent.indexOf (this);
951 if (itemIndex != -1) {
952 long hwnd = parent.handle;
953 LVITEM lvItem = new LVITEM ();
954 lvItem.mask = OS.LVIF_TEXT;
955 lvItem.iItem = itemIndex;
956 lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
957 OS.SendMessage (hwnd, OS.LVM_SETITEM, 0, lvItem);
961 parent.setScrollWidth (this, false);
963 redraw (index, true, false);
967 * Sets the receiver's foreground color to the color specified
968 * by the argument, or to the default system color for the item
969 * if the argument is null.
971 * @param color the new color (or null)
973 * @exception IllegalArgumentException <ul>
974 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
976 * @exception SWTException <ul>
977 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
978 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
983 public void setForeground (Color color){
985 if (color != null && color.isDisposed ()) {
986 error (SWT.ERROR_INVALID_ARGUMENT);
990 parent.setCustomDraw (true);
991 pixel = color.handle;
993 if (foreground == pixel) return;
995 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
1000 * Sets the foreground color at the given column index in the receiver
1001 * to the color specified by the argument, or to the default system color for the item
1002 * if the argument is null.
1004 * @param index the column index
1005 * @param color the new color (or null)
1007 * @exception IllegalArgumentException <ul>
1008 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
1010 * @exception SWTException <ul>
1011 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1012 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1017 public void setForeground (int index, Color color){
1019 if (color != null && color.isDisposed ()) {
1020 error (SWT.ERROR_INVALID_ARGUMENT);
1022 int count = Math.max (1, parent.getColumnCount ());
1023 if (0 > index || index > count - 1) return;
1025 if (color != null) {
1026 parent.setCustomDraw (true);
1027 pixel = color.handle;
1029 if (cellForeground == null) {
1030 cellForeground = new int [count];
1031 for (int i = 0; i < count; i++) {
1032 cellForeground [i] = -1;
1035 if (cellForeground [index] == pixel) return;
1036 cellForeground [index] = pixel;
1037 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
1038 redraw (index, true, false);
1042 * Sets the grayed state of the checkbox for this item. This state change
1043 * only applies if the Table was created with the SWT.CHECK style.
1045 * @param grayed the new grayed state of the checkbox;
1047 * @exception SWTException <ul>
1048 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1049 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1052 public void setGrayed (boolean grayed) {
1054 if ((parent.style & SWT.CHECK) == 0) return;
1055 if (this.grayed == grayed) return;
1056 this.grayed = grayed;
1057 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
1062 * Sets the image for multiple columns in the table.
1064 * @param images the array of new images
1066 * @exception IllegalArgumentException <ul>
1067 * <li>ERROR_NULL_ARGUMENT - if the array of images is null</li>
1068 * <li>ERROR_INVALID_ARGUMENT - if one of the images has been disposed</li>
1070 * @exception SWTException <ul>
1071 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1072 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1075 public void setImage (Image [] images) {
1077 if (images == null) error (SWT.ERROR_NULL_ARGUMENT);
1078 for (int i=0; i<images.length; i++) {
1079 setImage (i, images [i]);
1084 * Sets the receiver's image at a column.
1086 * @param index the column index
1087 * @param image the new image
1089 * @exception IllegalArgumentException <ul>
1090 * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
1092 * @exception SWTException <ul>
1093 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1094 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1097 public void setImage (int index, Image image) {
1099 if (image != null && image.isDisposed ()) {
1100 error(SWT.ERROR_INVALID_ARGUMENT);
1102 Image oldImage = null;
1104 if (image != null && image.type == SWT.ICON) {
1105 if (image.equals (this.image)) return;
1107 oldImage = this.image;
1108 super.setImage (image);
1110 int count = Math.max (1, parent.getColumnCount ());
1111 if (0 > index || index > count - 1) return;
1112 if (images == null && index != 0) {
1113 images = new Image [count];
1116 if (images != null) {
1117 if (image != null && image.type == SWT.ICON) {
1118 if (image.equals (images [index])) return;
1120 oldImage = images [index];
1121 images [index] = image;
1123 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
1125 /* Ensure that the image list is created */
1126 parent.imageIndex (image, index);
1128 if (index == 0) parent.setScrollWidth (this, false);
1129 boolean drawText = (image == null && oldImage != null) || (image != null && oldImage == null);
1130 redraw (index, drawText, true);
1134 public void setImage (Image image) {
1136 setImage (0, image);
1140 * Sets the indent of the first column's image, expressed in terms of the image's width.
1142 * @param indent the new indent
1144 * @exception SWTException <ul>
1145 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1146 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1149 * @deprecated this functionality is not supported on most platforms
1152 public void setImageIndent (int indent) {
1154 if (indent < 0) return;
1155 if (imageIndent == indent) return;
1156 imageIndent = indent;
1157 if ((parent.style & SWT.VIRTUAL) != 0) {
1160 int index = parent.indexOf (this);
1162 long hwnd = parent.handle;
1163 LVITEM lvItem = new LVITEM ();
1164 lvItem.mask = OS.LVIF_INDENT;
1165 lvItem.iItem = index;
1166 lvItem.iIndent = indent;
1167 OS.SendMessage (hwnd, OS.LVM_SETITEM, 0, lvItem);
1170 parent.setScrollWidth (this, false);
1175 * Sets the text for multiple columns in the table.
1177 * Note: If control characters like '\n', '\t' etc. are used
1178 * in the string, then the behavior is platform dependent.
1180 * @param strings the array of new strings
1182 * @exception IllegalArgumentException <ul>
1183 * <li>ERROR_NULL_ARGUMENT - if the text is null</li>
1185 * @exception SWTException <ul>
1186 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1187 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1190 public void setText (String [] strings) {
1192 if (strings == null) error (SWT.ERROR_NULL_ARGUMENT);
1193 for (int i=0; i<strings.length; i++) {
1194 String string = strings [i];
1195 if (string != null) setText (i, string);
1200 * Sets the receiver's text at a column
1202 * Note: If control characters like '\n', '\t' etc. are used
1203 * in the string, then the behavior is platform dependent.
1205 * @param index the column index
1206 * @param string the new text
1208 * @exception IllegalArgumentException <ul>
1209 * <li>ERROR_NULL_ARGUMENT - if the text is null</li>
1211 * @exception SWTException <ul>
1212 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1213 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1216 public void setText (int index, String string) {
1218 if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
1220 if (string.equals (text)) return;
1221 super.setText (string);
1223 int count = Math.max (1, parent.getColumnCount ());
1224 if (0 > index || index > count - 1) return;
1225 if (strings == null && index != 0) {
1226 strings = new String [count];
1229 if (strings != null) {
1230 if (string.equals (strings [index])) return;
1231 strings [index] = string;
1233 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
1236 * Bug in Windows. Despite the fact that every item in the
1237 * table always has LPSTR_TEXTCALLBACK, Windows caches the
1238 * bounds for the selected items. This means that
1239 * when you change the string to be something else, Windows
1240 * correctly asks you for the new string but when the item
1241 * is selected, the selection draws using the bounds of the
1242 * previous item. The fix is to reset LPSTR_TEXTCALLBACK
1243 * even though it has not changed, causing Windows to flush
1246 if ((parent.style & SWT.VIRTUAL) == 0 && cached) {
1247 int itemIndex = parent.indexOf (this);
1248 if (itemIndex != -1) {
1249 long hwnd = parent.handle;
1250 LVITEM lvItem = new LVITEM ();
1251 lvItem.mask = OS.LVIF_TEXT;
1252 lvItem.iItem = itemIndex;
1253 lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
1254 OS.SendMessage (hwnd, OS.LVM_SETITEM, 0, lvItem);
1258 parent.setScrollWidth (this, false);
1260 redraw (index, true, false);
1264 public void setText (String string) {
1266 setText (0, string);