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 a hierarchy of tree items in a tree widget.
27 * <dt><b>Styles:</b></dt>
29 * <dt><b>Events:</b></dt>
33 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
36 * @see <a href="http://www.eclipse.org/swt/snippets/#tree">Tree, TreeItem, TreeColumn snippets</a>
37 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
38 * @noextend This class is not intended to be subclassed by clients.
40 public class TreeItem extends Item {
42 * the handle to the OS resource
43 * (Warning: This field is platform dependent)
45 * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
46 * public API. It is marked public only so that it can be shared
47 * within the packages provided by SWT. It is not available on all
48 * platforms and should never be accessed from application code.
51 * @noreference This field is not intended to be referenced by clients.
60 int background = -1, foreground = -1;
61 int [] cellBackground, cellForeground;
64 * Constructs <code>TreeItem</code> and <em>inserts</em> it into <code>Tree</code>.
65 * Item is inserted as last direct child of the tree.
67 * For bulk insert scenarios, see TreeItem#TreeItem(Tree,int,int)
69 * @param parent a tree control which will be the parent of the new instance (cannot be null)
70 * @param style no styles are currently supported, pass SWT.NONE
72 * @exception IllegalArgumentException <ul>
73 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
75 * @exception SWTException <ul>
76 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
77 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
81 * @see Widget#checkSubclass
82 * @see Widget#getStyle
84 public TreeItem (Tree parent, int style) {
85 this (parent, style, OS.TVGN_ROOT, OS.TVI_LAST, 0);
89 * Constructs <code>TreeItem</code> and <em>inserts</em> it into <code>Tree</code>.
90 * Item is inserted as <code>index</code> direct child of the tree.
92 * The fastest way to insert many items is:
94 * <li>Use {@link Tree#setRedraw} to disable drawing during bulk insert</li>
95 * <li>Insert every item at index 0 (insert them in reverse to get the same result)</li>
98 * @param parent a tree control which will be the parent of the new instance (cannot be null)
99 * @param style no styles are currently supported, pass SWT.NONE
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
114 * @see Tree#setRedraw
116 public TreeItem (Tree parent, int style, int index) {
117 this (parent, style, OS.TVGN_ROOT, findPrevious (parent, index), 0);
121 * Constructs <code>TreeItem</code> and <em>inserts</em> it into <code>Tree</code>.
122 * Item is inserted as last direct child of the specified <code>TreeItem</code>.
124 * For bulk insert scenarios, see TreeItem#TreeItem(TreeItem,int,int)
126 * @param parentItem a tree control which will be the parent of the new instance (cannot be null)
127 * @param style no styles are currently supported, pass SWT.NONE
129 * @exception IllegalArgumentException <ul>
130 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
132 * @exception SWTException <ul>
133 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
134 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
138 * @see Widget#checkSubclass
139 * @see Widget#getStyle
141 public TreeItem (TreeItem parentItem, int style) {
142 this (checkNull (parentItem).parent, style, parentItem.handle, OS.TVI_LAST, 0);
146 * Constructs <code>TreeItem</code> and <em>inserts</em> it into <code>Tree</code>.
147 * Item is inserted as <code>index</code> direct child of the specified <code>TreeItem</code>.
149 * The fastest way to insert many items is:
151 * <li>Use {@link Tree#setRedraw} to disable drawing during bulk insert</li>
152 * <li>Insert child items while parent item is collapsed</li>
153 * <li>Insert every item at index 0 (insert them in reverse to get the same result)</li>
156 * @param parentItem a tree control which will be the parent of the new instance (cannot be null)
157 * @param style no styles are currently supported, pass SWT.NONE
158 * @param index the zero-relative index to store the receiver in its parent
160 * @exception IllegalArgumentException <ul>
161 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
162 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
164 * @exception SWTException <ul>
165 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
166 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
170 * @see Widget#checkSubclass
171 * @see Widget#getStyle
172 * @see Tree#setRedraw
174 public TreeItem (TreeItem parentItem, int style, int index) {
175 this (checkNull (parentItem).parent, style, parentItem.handle, findPrevious (parentItem, index), 0);
178 TreeItem (Tree parent, int style, long hParent, long hInsertAfter, long hItem) {
179 super (parent, style);
180 this.parent = parent;
181 parent.createItem (this, hParent, hInsertAfter, hItem);
184 static TreeItem checkNull (TreeItem item) {
185 if (item == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
189 static long findPrevious (Tree parent, int index) {
190 if (parent == null) return 0;
191 if (index < 0) SWT.error (SWT.ERROR_INVALID_RANGE);
192 if (index == 0) return OS.TVI_FIRST;
193 long hwnd = parent.handle;
194 long hFirstItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
195 long hItem = parent.findItem (hFirstItem, index - 1);
196 if (hItem == 0) SWT.error (SWT.ERROR_INVALID_RANGE);
200 static long findPrevious (TreeItem parentItem, int index) {
201 if (parentItem == null) return 0;
202 if (index < 0) SWT.error (SWT.ERROR_INVALID_RANGE);
203 if (index == 0) return OS.TVI_FIRST;
204 Tree parent = parentItem.parent;
205 long hwnd = parent.handle, hParent = parentItem.handle;
206 long hFirstItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hParent);
207 long hItem = parent.findItem (hFirstItem, index - 1);
208 if (hItem == 0) SWT.error (SWT.ERROR_INVALID_RANGE);
213 protected void checkSubclass () {
214 if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
222 if ((parent.style & SWT.CHECK) != 0) {
223 long hwnd = parent.handle;
224 TVITEM tvItem = new TVITEM ();
225 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
226 tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
227 tvItem.state = 1 << 12;
228 tvItem.hItem = handle;
229 OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, tvItem);
231 background = foreground = -1;
233 cellBackground = cellForeground = null;
235 if ((parent.style & SWT.VIRTUAL) != 0) cached = false;
239 * Clears the item at the given zero-relative index in the receiver.
240 * The text, icon and other attributes of the item are set to the default
241 * value. If the tree was created with the <code>SWT.VIRTUAL</code> style,
242 * these attributes are requested again as needed.
244 * @param index the index of the item to clear
245 * @param all <code>true</code> if all child items of the indexed item should be
246 * cleared recursively, and <code>false</code> otherwise
248 * @exception IllegalArgumentException <ul>
249 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
251 * @exception SWTException <ul>
252 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
253 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
261 public void clear (int index, boolean all) {
263 long hwnd = parent.handle;
264 long hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
265 if (hItem == 0) error (SWT.ERROR_INVALID_RANGE);
266 hItem = parent.findItem (hItem, index);
267 if (hItem == 0) error (SWT.ERROR_INVALID_RANGE);
268 TVITEM tvItem = new TVITEM ();
269 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
270 parent.clear (hItem, tvItem);
272 hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
273 parent.clearAll (hItem, tvItem, all);
278 * Clears all the items in the receiver. The text, icon and other
279 * attributes of the items are set to their default values. If the
280 * tree was created with the <code>SWT.VIRTUAL</code> style, these
281 * attributes are requested again as needed.
283 * @param all <code>true</code> if all child items should be cleared
284 * recursively, and <code>false</code> otherwise
286 * @exception SWTException <ul>
287 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
288 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
296 public void clearAll (boolean all) {
298 long hwnd = parent.handle;
299 long hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
300 if (hItem == 0) return;
301 TVITEM tvItem = new TVITEM ();
302 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
303 parent.clearAll (hItem, tvItem, all);
307 void destroyWidget () {
308 TVITEM tvItem = new TVITEM ();
309 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
310 parent.releaseItem (handle, tvItem, false);
311 parent.destroyItem (this, handle);
315 long fontHandle (int index) {
316 if (cellFont != null && cellFont [index] != null) return cellFont [index].handle;
317 if (font != null) return font.handle;
322 * Returns the receiver's background color.
324 * @return the background color
326 * @exception SWTException <ul>
327 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
328 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
334 public Color getBackground () {
336 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
337 if (background == -1) return parent.getBackground ();
338 return Color.win32_new (display, background);
342 * Returns the background color at the given column index in the receiver.
344 * @param index the column index
345 * @return the background color
347 * @exception SWTException <ul>
348 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
349 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
354 public Color getBackground (int index) {
356 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
357 int count = Math.max (1, parent.getColumnCount ());
358 if (0 > index || index > count - 1) return getBackground ();
359 int pixel = cellBackground != null ? cellBackground [index] : -1;
360 return pixel == -1 ? getBackground () : Color.win32_new (display, pixel);
364 * Returns a rectangle describing the size and location of the receiver's
365 * text relative to its parent.
367 * @return the bounding rectangle of the receiver's text
369 * @exception SWTException <ul>
370 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
371 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
374 public Rectangle getBounds () {
376 return DPIUtil.autoScaleDown(getBoundsInPixels());
379 Rectangle getBoundsInPixels () {
380 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
381 RECT rect = getBounds (0, true, false, false);
382 int width = rect.right - rect.left, height = rect.bottom - rect.top;
383 return new Rectangle (rect.left, rect.top, width, height);
387 * Returns a rectangle describing the receiver's size and location
388 * relative to its parent at a column in the tree.
390 * @param index the index that specifies the column
391 * @return the receiver's bounding column rectangle
393 * @exception SWTException <ul>
394 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
395 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
400 public Rectangle getBounds (int index) {
402 return DPIUtil.autoScaleDown(getBoundsInPixels(index));
405 Rectangle getBoundsInPixels (int index) {
406 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
407 RECT rect = getBounds (index, true, true, true);
408 int width = rect.right - rect.left, height = rect.bottom - rect.top;
409 return new Rectangle (rect.left, rect.top, width, height);
412 RECT getBounds (int index, boolean getText, boolean getImage, boolean fullText) {
413 return getBounds (index, getText, getImage, fullText, false, true, 0);
416 //TODO - take into account grid (add boolean arg) to damage less during redraw
417 RECT getBounds (int index, boolean getText, boolean getImage, boolean fullText, boolean fullImage, boolean clip, long hDC) {
418 if (!getText && !getImage) return new RECT ();
419 long hwnd = parent.handle;
420 if ((parent.style & SWT.VIRTUAL) == 0 && !cached && !parent.painted) {
421 TVITEM tvItem = new TVITEM ();
422 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_TEXT;
423 tvItem.hItem = handle;
424 tvItem.pszText = OS.LPSTR_TEXTCALLBACK;
425 parent.ignoreCustomDraw = true;
426 OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, tvItem);
427 parent.ignoreCustomDraw = false;
429 boolean firstColumn = index == 0;
431 long hwndHeader = parent.hwndHeader;
432 if (hwndHeader != 0) {
433 columnCount = parent.columnCount;
434 firstColumn = index == OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
436 RECT rect = new RECT ();
438 boolean full = columnCount == 0 && getText && getImage && fullText && fullImage;
439 if (!OS.TreeView_GetItemRect (hwnd, handle, rect, !full)) {
442 if (getImage && !fullImage) {
443 if (OS.SendMessage (hwnd, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0) != 0) {
444 Point size = parent.getImageSize ();
445 rect.left -= size.x + Tree.INSET;
446 if (!getText) rect.right = rect.left + size.x;
448 if (!getText) rect.right = rect.left;
451 if (fullText || fullImage || clip) {
452 if (hwndHeader != 0) {
453 RECT headerRect = new RECT ();
454 if (columnCount != 0) {
455 if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, headerRect) == 0) {
459 headerRect.right = parent.scrollWidth;
460 if (headerRect.right == 0) headerRect = rect;
462 if (fullText && clip) rect.right = headerRect.right;
463 if (fullImage) rect.left = headerRect.left;
464 if (clip && headerRect.right < rect.right) {
465 rect.right = headerRect.right;
470 if (!(0 <= index && index < columnCount)) return new RECT ();
471 RECT headerRect = new RECT ();
472 if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, headerRect) == 0) {
475 if (!OS.TreeView_GetItemRect (hwnd, handle, rect, false)) {
478 rect.left = headerRect.left;
479 if (fullText && getImage && clip) {
480 rect.right = headerRect.right;
482 rect.right = headerRect.left;
487 if (images != null) image = images [index];
490 Point size = parent.getImageSize ();
491 rect.right += size.x;
494 if (fullText && clip) {
495 rect.left = rect.right + Tree.INSET;
496 rect.right = headerRect.right;
498 String string = index == 0 ? text : strings != null ? strings [index] : null;
499 if (string != null) {
500 RECT textRect = new RECT ();
501 char [] buffer = string.toCharArray ();
502 int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_CALCRECT;
503 long hNewDC = hDC, hFont = 0;
505 hNewDC = OS.GetDC (hwnd);
506 hFont = fontHandle (index);
507 if (hFont == -1) hFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
508 hFont = OS.SelectObject (hNewDC, hFont);
510 OS.DrawText (hNewDC, buffer, buffer.length, textRect, flags);
512 OS.SelectObject (hNewDC, hFont);
513 OS.ReleaseDC (hwnd, hNewDC);
516 rect.right += textRect.right - textRect.left + Tree.INSET * 3;
518 rect.left = rect.right + Tree.INSET;
519 rect.right = rect.left + (textRect.right - textRect.left) + Tree.INSET;
524 if (clip && headerRect.right < rect.right) {
525 rect.right = headerRect.right;
529 int gridWidth = parent.linesVisible && columnCount != 0 ? Tree.GRID_WIDTH : 0;
530 if (getText || !getImage) {
531 rect.right = Math.max (rect.left, rect.right - gridWidth);
533 rect.bottom = Math.max (rect.top, rect.bottom - gridWidth);
538 * Returns <code>true</code> if the receiver is checked,
539 * and false otherwise. When the parent does not have
540 * the <code>CHECK</code> style, return false.
542 * @return the checked state
544 * @exception SWTException <ul>
545 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
546 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
549 public boolean getChecked () {
551 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
552 if ((parent.style & SWT.CHECK) == 0) return false;
553 long hwnd = parent.handle;
554 TVITEM tvItem = new TVITEM ();
555 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
556 tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
557 tvItem.hItem = handle;
558 long result = OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, tvItem);
559 return (result != 0) && (((tvItem.state >> 12) & 1) == 0);
563 * Returns <code>true</code> if the receiver is expanded,
564 * and false otherwise.
567 * @return the expanded state
569 * @exception SWTException <ul>
570 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
571 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
574 public boolean getExpanded () {
576 long hwnd = parent.handle;
578 * Bug in Windows. Despite the fact that TVM_GETITEMSTATE claims
579 * to return only the bits specified by the stateMask, when called
580 * with TVIS_EXPANDED, the entire state is returned. The fix is
581 * to explicitly check for the TVIS_EXPANDED bit.
583 int state = (int)OS.SendMessage (hwnd, OS.TVM_GETITEMSTATE, handle, OS.TVIS_EXPANDED);
584 return (state & OS.TVIS_EXPANDED) != 0;
588 * Returns the font that the receiver will use to paint textual information for this item.
590 * @return the receiver's font
592 * @exception SWTException <ul>
593 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
594 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
599 public Font getFont () {
601 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
602 return font != null ? font : parent.getFont ();
606 * Returns the font that the receiver will use to paint textual information
607 * for the specified cell in this item.
609 * @param index the column index
610 * @return the receiver's font
612 * @exception SWTException <ul>
613 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
614 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
619 public Font getFont (int index) {
621 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
622 int count = Math.max (1, parent.getColumnCount ());
623 if (0 > index || index > count -1) return getFont ();
624 if (cellFont == null || cellFont [index] == null) return getFont ();
625 return cellFont [index];
629 * Returns the foreground color that the receiver will use to draw.
631 * @return the receiver's foreground color
633 * @exception SWTException <ul>
634 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
635 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
641 public Color getForeground () {
643 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
644 if (foreground == -1) return parent.getForeground ();
645 return Color.win32_new (display, foreground);
650 * Returns the foreground color at the given column index in the receiver.
652 * @param index the column index
653 * @return the foreground color
655 * @exception SWTException <ul>
656 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
657 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
662 public Color getForeground (int index) {
664 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
665 int count = Math.max (1, parent.getColumnCount ());
666 if (0 > index || index > count -1) return getForeground ();
667 int pixel = cellForeground != null ? cellForeground [index] : -1;
668 return pixel == -1 ? getForeground () : Color.win32_new (display, pixel);
672 * Returns <code>true</code> if the receiver is grayed,
673 * and false otherwise. When the parent does not have
674 * the <code>CHECK</code> style, return false.
676 * @return the grayed state of the checkbox
678 * @exception SWTException <ul>
679 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
680 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
683 public boolean getGrayed () {
685 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
686 if ((parent.style & SWT.CHECK) == 0) return false;
687 long hwnd = parent.handle;
688 TVITEM tvItem = new TVITEM ();
689 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
690 tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
691 tvItem.hItem = handle;
692 long result = OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, tvItem);
693 return (result != 0) && ((tvItem.state >> 12) > 2);
697 * Returns the item at the given, zero-relative index in the
698 * receiver. Throws an exception if the index is out of range.
700 * @param index the index of the item to return
701 * @return the item at the given index
703 * @exception IllegalArgumentException <ul>
704 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
706 * @exception SWTException <ul>
707 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
708 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
713 public TreeItem getItem (int index) {
715 if (index < 0) error (SWT.ERROR_INVALID_RANGE);
716 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
717 long hwnd = parent.handle;
718 long hFirstItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
719 if (hFirstItem == 0) error (SWT.ERROR_INVALID_RANGE);
720 long hItem = parent.findItem (hFirstItem, index);
721 if (hItem == 0) error (SWT.ERROR_INVALID_RANGE);
722 return parent._getItem (hItem);
726 * Returns the number of items contained in the receiver
727 * that are direct item children of the receiver.
729 * @return the number of items
731 * @exception SWTException <ul>
732 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
733 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
736 public int getItemCount () {
738 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
739 long hwnd = parent.handle;
740 long hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
741 if (hItem == 0) return 0;
742 return parent.getItemCount (hItem);
746 * Returns a (possibly empty) array of <code>TreeItem</code>s which
747 * are the direct item children of the receiver.
749 * Note: This is not the actual structure used by the receiver
750 * to maintain its list of items, so modifying the array will
751 * not affect the receiver.
754 * @return the receiver's items
756 * @exception SWTException <ul>
757 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
758 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
761 public TreeItem [] getItems () {
763 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
764 long hwnd = parent.handle;
765 long hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
766 if (hItem == 0) return new TreeItem [0];
767 return parent.getItems (hItem);
771 public Image getImage () {
773 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
774 return super.getImage ();
778 * Returns the image stored at the given column index in the receiver,
779 * or null if the image has not been set or if the column does not exist.
781 * @param index the column index
782 * @return the image stored at the given column index in the receiver
784 * @exception SWTException <ul>
785 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
786 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
791 public Image getImage (int index) {
793 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
794 if (index == 0) return getImage ();
795 if (images != null) {
796 if (0 <= index && index < images.length) return images [index];
802 * Returns a rectangle describing the size and location
803 * relative to its parent of an image at a column in the
806 * @param index the index that specifies the column
807 * @return the receiver's bounding image rectangle
809 * @exception SWTException <ul>
810 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
811 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
816 public Rectangle getImageBounds (int index) {
818 return DPIUtil.autoScaleDown(getImageBoundsInPixels(index));
821 Rectangle getImageBoundsInPixels (int index) {
822 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
823 RECT rect = getBounds (index, false, true, false);
824 int width = rect.right - rect.left, height = rect.bottom - rect.top;
825 return new Rectangle (rect.left, rect.top, width, height);
829 * Returns the receiver's parent, which must be a <code>Tree</code>.
831 * @return the receiver's parent
833 * @exception SWTException <ul>
834 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
835 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
838 public Tree getParent () {
844 * Returns the receiver's parent item, which must be a
845 * <code>TreeItem</code> or null when the receiver is a
848 * @return the receiver's parent item
850 * @exception SWTException <ul>
851 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
852 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
855 public TreeItem getParentItem () {
857 long hwnd = parent.handle;
858 long hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, handle);
859 return hItem != 0 ? parent._getItem (hItem) : null;
863 public String getText () {
865 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
866 return super.getText ();
870 * Returns the text stored at the given column index in the receiver,
871 * or empty string if the text has not been set.
873 * @param index the column index
874 * @return the text stored at the given column index in the receiver
876 * @exception SWTException <ul>
877 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
878 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
883 public String getText (int index) {
885 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
886 if (index == 0) return getText ();
887 if (strings != null) {
888 if (0 <= index && index < strings.length) {
889 String string = strings [index];
890 return string != null ? string : "";
897 * Returns a rectangle describing the size and location
898 * relative to its parent of the text at a column in the
901 * @param index the index that specifies the column
902 * @return the receiver's bounding text rectangle
904 * @exception SWTException <ul>
905 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
906 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
911 public Rectangle getTextBounds (int index) {
913 return DPIUtil.autoScaleDown(getTextBoundsInPixels(index));
916 Rectangle getTextBoundsInPixels (int index) {
917 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
918 RECT rect = getBounds (index, true, false, true);
919 if (index == 0) rect.left += Tree.INSET - 1;
920 rect.left = Math.min (rect.left, rect.right);
921 rect.right = rect.right - Tree.INSET;
922 int width = Math.max (0, rect.right - rect.left);
923 int height = Math.max (0, rect.bottom - rect.top);
924 return new Rectangle (rect.left, rect.top, width, height);
928 * Searches the receiver's list starting at the first item
929 * (index 0) until an item is found that is equal to the
930 * argument, and returns the index of that item. If no item
931 * is found, returns -1.
933 * @param item the search item
934 * @return the index of the item
936 * @exception IllegalArgumentException <ul>
937 * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
938 * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li>
940 * @exception SWTException <ul>
941 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
942 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
947 public int indexOf (TreeItem item) {
949 if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
950 if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
951 long hwnd = parent.handle;
952 long hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
953 return hItem == 0 ? -1 : parent.findIndex (hItem, item.handle);
957 if (parent.currentItem == this || !parent.getDrawing ()) return;
958 long hwnd = parent.handle;
959 if (!OS.IsWindowVisible (hwnd)) return;
961 * When there are no columns and the tree is not
962 * full selection, redraw only the text. This is
963 * an optimization to reduce flashing.
965 boolean full = (parent.style & (SWT.FULL_SELECTION | SWT.VIRTUAL)) != 0;
967 full = parent.columnCount != 0;
969 if (parent.hooks (SWT.EraseItem) || parent.hooks (SWT.PaintItem)) {
974 RECT rect = new RECT ();
975 if (OS.TreeView_GetItemRect (hwnd, handle, rect, !full)) {
976 OS.InvalidateRect (hwnd, rect, true);
980 void redraw (int column, boolean drawText, boolean drawImage) {
981 if (parent.currentItem == this || !parent.getDrawing ()) return;
982 long hwnd = parent.handle;
983 if (!OS.IsWindowVisible (hwnd)) return;
984 boolean fullImage = column == 0 && drawText && drawImage;
985 RECT rect = getBounds (column, drawText, drawImage, true, fullImage, true, 0);
986 OS.InvalidateRect (hwnd, rect, true);
990 void releaseChildren (boolean destroy) {
992 TVITEM tvItem = new TVITEM ();
993 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
994 parent.releaseItems (handle, tvItem);
996 super.releaseChildren (destroy);
1000 void releaseHandle () {
1001 super.releaseHandle ();
1007 void releaseWidget () {
1008 super.releaseWidget ();
1011 cellBackground = cellForeground = null;
1016 * Removes all of the items from the receiver.
1018 * @exception SWTException <ul>
1019 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1020 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1025 public void removeAll () {
1027 long hwnd = parent.handle;
1028 TVITEM tvItem = new TVITEM ();
1029 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
1030 tvItem.hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
1031 while (tvItem.hItem != 0) {
1032 OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, tvItem);
1033 TreeItem item = tvItem.lParam != -1 ? parent.items [(int)tvItem.lParam] : null;
1034 if (item != null && !item.isDisposed ()) {
1037 parent.releaseItem (tvItem.hItem, tvItem, false);
1038 parent.destroyItem (null, tvItem.hItem);
1040 tvItem.hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
1045 * Sets the receiver's background color to the color specified
1046 * by the argument, or to the default system color for the item
1047 * if the argument is null.
1049 * @param color the new color (or null)
1051 * @exception IllegalArgumentException <ul>
1052 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
1054 * @exception SWTException <ul>
1055 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1056 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1062 public void setBackground (Color color) {
1064 if (color != null && color.isDisposed ()) {
1065 error (SWT.ERROR_INVALID_ARGUMENT);
1068 if (color != null) {
1069 parent.customDraw = true;
1070 pixel = color.handle;
1072 if (background == pixel) return;
1074 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
1079 * Sets the background color at the given column index in the receiver
1080 * to the color specified by the argument, or to the default system color for the item
1081 * if the argument is null.
1083 * @param index the column index
1084 * @param color the new color (or null)
1086 * @exception IllegalArgumentException <ul>
1087 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
1089 * @exception SWTException <ul>
1090 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1091 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1097 public void setBackground (int index, Color color) {
1099 if (color != null && color.isDisposed ()) {
1100 error (SWT.ERROR_INVALID_ARGUMENT);
1102 int count = Math.max (1, parent.getColumnCount ());
1103 if (0 > index || index > count - 1) return;
1105 if (color != null) {
1106 parent.customDraw = true;
1107 pixel = color.handle;
1109 if (cellBackground == null) {
1110 cellBackground = new int [count];
1111 for (int i = 0; i < count; i++) {
1112 cellBackground [i] = -1;
1115 if (cellBackground [index] == pixel) return;
1116 cellBackground [index] = pixel;
1117 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
1118 redraw (index, true, true);
1122 * Sets the checked state of the receiver.
1125 * @param checked the new checked state
1127 * @exception SWTException <ul>
1128 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1129 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1132 public void setChecked (boolean checked) {
1134 if ((parent.style & SWT.CHECK) == 0) return;
1135 long hwnd = parent.handle;
1136 TVITEM tvItem = new TVITEM ();
1137 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
1138 tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
1139 tvItem.hItem = handle;
1140 OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, tvItem);
1141 int state = tvItem.state >> 12;
1143 if ((state & 0x1) != 0) state++;
1145 if ((state & 0x1) == 0) --state;
1148 if (tvItem.state == state) return;
1149 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
1150 tvItem.state = state;
1151 OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, tvItem);
1153 * Bug in Windows. When TVM_SETITEM is used to set
1154 * the state image of an item inside TVN_GETDISPINFO,
1155 * the new state is not redrawn. The fix is to force
1158 if ((parent.style & SWT.VIRTUAL) != 0) {
1159 if (parent.currentItem == this && OS.IsWindowVisible (hwnd)) {
1160 RECT rect = new RECT ();
1161 if (OS.TreeView_GetItemRect (hwnd, handle, rect, false)) {
1162 OS.InvalidateRect (hwnd, rect, true);
1169 * Sets the expanded state of the receiver.
1172 * @param expanded the new expanded state
1174 * @exception SWTException <ul>
1175 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1176 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1179 public void setExpanded (boolean expanded) {
1182 /* Do nothing when the item is a leaf or already expanded */
1183 long hwnd = parent.handle;
1184 if (OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle) == 0) {
1188 * Bug in Windows. Despite the fact that TVM_GETITEMSTATE claims
1189 * to return only the bits specified by the stateMask, when called
1190 * with TVIS_EXPANDED, the entire state is returned. The fix is
1191 * to explicitly check for the TVIS_EXPANDED bit.
1193 int state = (int)OS.SendMessage (hwnd, OS.TVM_GETITEMSTATE, handle, OS.TVIS_EXPANDED);
1194 if (((state & OS.TVIS_EXPANDED) != 0) == expanded) return;
1197 * Feature in Windows. When TVM_EXPAND is used to expand
1198 * an item, the widget scrolls to show the item and the
1199 * newly expanded items. While not strictly incorrect,
1200 * this means that application code that expands tree items
1201 * in a background thread can scroll the widget while the
1202 * user is interacting with it. The fix is to remember
1203 * the top item and the bounds of every tree item, turn
1204 * redraw off, expand the item, scroll back to the top
1205 * item. If none of the rectangles have moved, then
1206 * it is safe to turn redraw back on without redrawing
1209 RECT oldRect = null;
1210 RECT [] rects = null;
1211 SCROLLINFO oldInfo = null;
1213 long hBottomItem = 0;
1214 boolean redraw = false, noScroll = true;
1215 long hTopItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
1216 if (noScroll && hTopItem != 0) {
1217 oldInfo = new SCROLLINFO ();
1218 oldInfo.cbSize = SCROLLINFO.sizeof;
1219 oldInfo.fMask = OS.SIF_ALL;
1220 if (!OS.GetScrollInfo (hwnd, OS.SB_HORZ, oldInfo)) {
1223 if (parent.getDrawing () && OS.IsWindowVisible (hwnd)) {
1224 boolean noAnimate = true;
1225 count = (int)OS.SendMessage (hwnd, OS.TVM_GETVISIBLECOUNT, 0, 0);
1226 rects = new RECT [count + 1];
1227 long hItem = hTopItem;
1229 while (hItem != 0 && (noAnimate || hItem != handle) && index < count) {
1230 RECT rect = new RECT ();
1231 if (OS.TreeView_GetItemRect (hwnd, hItem, rect, true)) {
1232 rects [index++] = rect;
1234 hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
1236 if (noAnimate || hItem != handle) {
1239 hBottomItem = hItem;
1240 oldRect = new RECT ();
1241 OS.GetClientRect (hwnd, oldRect);
1242 long topHandle = parent.topHandle ();
1243 OS.UpdateWindow (topHandle);
1244 OS.DefWindowProc (topHandle, OS.WM_SETREDRAW, 0, 0);
1245 if (hwnd != topHandle) {
1246 OS.UpdateWindow (hwnd);
1247 OS.DefWindowProc (hwnd, OS.WM_SETREDRAW, 0, 0);
1250 * This code is intentionally commented.
1252 // OS.SendMessage (hwnd, OS.WM_SETREDRAW, 0, 0);
1258 * Feature in Windows. When the user collapses the root
1259 * of a subtree that has the focus item, Windows moves
1260 * the selection to the root of the subtree and issues
1261 * a TVN_SELCHANGED to inform the programmer that the
1262 * selection has changed. When the programmer collapses
1263 * the same subtree using TVM_EXPAND, Windows does not
1264 * send the selection changed notification. This is not
1265 * strictly wrong but is inconsistent. The fix is to
1266 * check whether the selection has changed and issue
1269 long hOldItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
1271 /* Expand or collapse the item */
1272 parent.ignoreExpand = true;
1273 OS.SendMessage (hwnd, OS.TVM_EXPAND, expanded ? OS.TVE_EXPAND : OS.TVE_COLLAPSE, handle);
1274 parent.ignoreExpand = false;
1276 /* Scroll back to the top item */
1277 if (noScroll && hTopItem != 0) {
1278 boolean collapsed = false;
1280 RECT rect = new RECT ();
1281 while (hTopItem != 0 && !OS.TreeView_GetItemRect (hwnd, hTopItem, rect, false)) {
1282 hTopItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hTopItem);
1286 boolean scrolled = true;
1287 if (hTopItem != 0) {
1288 OS.SendMessage (hwnd, OS.TVM_SELECTITEM, OS.TVGN_FIRSTVISIBLE, hTopItem);
1289 scrolled = hTopItem != OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
1291 if (!collapsed && !scrolled && oldInfo != null) {
1292 SCROLLINFO newInfo = new SCROLLINFO ();
1293 newInfo.cbSize = SCROLLINFO.sizeof;
1294 newInfo.fMask = OS.SIF_ALL;
1295 if (OS.GetScrollInfo (hwnd, OS.SB_HORZ, newInfo)) {
1296 if (oldInfo.nPos != newInfo.nPos) {
1297 long lParam = OS.MAKELPARAM (OS.SB_THUMBPOSITION, oldInfo.nPos);
1298 OS.SendMessage (hwnd, OS.WM_HSCROLL, lParam, 0);
1303 boolean fixScroll = false;
1304 if (!collapsed && !scrolled) {
1305 RECT newRect = new RECT ();
1306 OS.GetClientRect (hwnd, newRect);
1307 if (OS.EqualRect (oldRect, newRect)) {
1308 long hItem = hTopItem;
1310 while (hItem != 0 && index < count) {
1311 RECT rect = new RECT ();
1312 if (OS.TreeView_GetItemRect (hwnd, hItem, rect, true)) {
1313 if (!OS.EqualRect (rect, rects [index])) {
1317 hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
1320 fixScroll = index == count && hItem == hBottomItem;
1323 long topHandle = parent.topHandle ();
1324 OS.DefWindowProc (topHandle, OS.WM_SETREDRAW, 1, 0);
1325 if (hwnd != topHandle) {
1326 OS.DefWindowProc (hwnd, OS.WM_SETREDRAW, 1, 0);
1329 * This code is intentionally commented.
1331 // OS.SendMessage (hwnd, OS.WM_SETREDRAW, 1, 0);
1333 parent.updateScrollBar ();
1334 SCROLLINFO info = new SCROLLINFO ();
1335 info.cbSize = SCROLLINFO.sizeof;
1336 info.fMask = OS.SIF_ALL;
1337 if (OS.GetScrollInfo (hwnd, OS.SB_VERT, info)) {
1338 OS.SetScrollInfo (hwnd, OS.SB_VERT, info, true);
1340 if (handle == hBottomItem) {
1341 RECT rect = new RECT ();
1342 if (OS.TreeView_GetItemRect (hwnd, hBottomItem, rect, false)) {
1343 OS.InvalidateRect (hwnd, rect, true);
1347 int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
1348 OS.RedrawWindow (topHandle, null, 0, flags);
1353 /* Check for a selection event */
1354 long hNewItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
1355 if (hNewItem != hOldItem) {
1356 Event event = new Event ();
1357 if (hNewItem != 0) {
1358 event.item = parent._getItem (hNewItem);
1359 parent.hAnchor = hNewItem;
1361 parent.sendSelectionEvent (SWT.Selection, event, true);
1366 * Sets the font that the receiver will use to paint textual information
1367 * for this item to the font specified by the argument, or to the default font
1368 * for that kind of control if the argument is null.
1370 * @param font the new font (or null)
1372 * @exception IllegalArgumentException <ul>
1373 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
1375 * @exception SWTException <ul>
1376 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1377 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1382 public void setFont (Font font){
1384 if (font != null && font.isDisposed ()) {
1385 error (SWT.ERROR_INVALID_ARGUMENT);
1387 Font oldFont = this.font;
1388 if (oldFont == font) return;
1390 if (oldFont != null && oldFont.equals (font)) return;
1391 if (font != null) parent.customDraw = true;
1392 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
1394 * Bug in Windows. When the font is changed for an item,
1395 * the bounds for the item are not updated, causing the text
1396 * to be clipped. The fix is to reset the text, causing
1397 * Windows to compute the new bounds using the new font.
1399 if ((parent.style & SWT.VIRTUAL) == 0 && !cached && !parent.painted) {
1402 long hwnd = parent.handle;
1403 TVITEM tvItem = new TVITEM ();
1404 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_TEXT;
1405 tvItem.hItem = handle;
1406 tvItem.pszText = OS.LPSTR_TEXTCALLBACK;
1407 OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, tvItem);
1412 * Sets the font that the receiver will use to paint textual information
1413 * for the specified cell in this item to the font specified by the
1414 * argument, or to the default font for that kind of control if the
1417 * @param index the column index
1418 * @param font the new font (or null)
1420 * @exception IllegalArgumentException <ul>
1421 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
1423 * @exception SWTException <ul>
1424 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1425 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1430 public void setFont (int index, Font font) {
1432 if (font != null && font.isDisposed ()) {
1433 error (SWT.ERROR_INVALID_ARGUMENT);
1435 int count = Math.max (1, parent.getColumnCount ());
1436 if (0 > index || index > count - 1) return;
1437 if (cellFont == null) {
1438 if (font == null) return;
1439 cellFont = new Font [count];
1441 Font oldFont = cellFont [index];
1442 if (oldFont == font) return;
1443 cellFont [index] = font;
1444 if (oldFont != null && oldFont.equals (font)) return;
1445 if (font != null) parent.customDraw = true;
1446 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
1448 * Bug in Windows. When the font is changed for an item,
1449 * the bounds for the item are not updated, causing the text
1450 * to be clipped. The fix is to reset the text, causing
1451 * Windows to compute the new bounds using the new font.
1454 if ((parent.style & SWT.VIRTUAL) == 0 && !cached && !parent.painted) {
1457 long hwnd = parent.handle;
1458 TVITEM tvItem = new TVITEM ();
1459 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_TEXT;
1460 tvItem.hItem = handle;
1461 tvItem.pszText = OS.LPSTR_TEXTCALLBACK;
1462 OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, tvItem);
1464 redraw (index, true, false);
1469 * Sets the receiver's foreground color to the color specified
1470 * by the argument, or to the default system color for the item
1471 * if the argument is null.
1473 * @param color the new color (or null)
1475 * @exception IllegalArgumentException <ul>
1476 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
1478 * @exception SWTException <ul>
1479 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1480 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1486 public void setForeground (Color color) {
1488 if (color != null && color.isDisposed ()) {
1489 error (SWT.ERROR_INVALID_ARGUMENT);
1492 if (color != null) {
1493 parent.customDraw = true;
1494 pixel = color.handle;
1496 if (foreground == pixel) return;
1498 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
1503 * Sets the foreground color at the given column index in the receiver
1504 * to the color specified by the argument, or to the default system color for the item
1505 * if the argument is null.
1507 * @param index the column index
1508 * @param color the new color (or null)
1510 * @exception IllegalArgumentException <ul>
1511 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
1513 * @exception SWTException <ul>
1514 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1515 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1521 public void setForeground (int index, Color color){
1523 if (color != null && color.isDisposed ()) {
1524 error (SWT.ERROR_INVALID_ARGUMENT);
1526 int count = Math.max (1, parent.getColumnCount ());
1527 if (0 > index || index > count - 1) return;
1529 if (color != null) {
1530 parent.customDraw = true;
1531 pixel = color.handle;
1533 if (cellForeground == null) {
1534 cellForeground = new int [count];
1535 for (int i = 0; i < count; i++) {
1536 cellForeground [i] = -1;
1539 if (cellForeground [index] == pixel) return;
1540 cellForeground [index] = pixel;
1541 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
1542 redraw (index, true, false);
1546 * Sets the grayed state of the checkbox for this item. This state change
1547 * only applies if the Tree was created with the SWT.CHECK style.
1549 * @param grayed the new grayed state of the checkbox
1551 * @exception SWTException <ul>
1552 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1553 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1556 public void setGrayed (boolean grayed) {
1558 if ((parent.style & SWT.CHECK) == 0) return;
1559 long hwnd = parent.handle;
1560 TVITEM tvItem = new TVITEM ();
1561 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
1562 tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
1563 tvItem.hItem = handle;
1564 OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, tvItem);
1565 int state = tvItem.state >> 12;
1567 if (state <= 2) state +=2;
1569 if (state > 2) state -=2;
1572 if (tvItem.state == state) return;
1573 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
1574 tvItem.state = state;
1575 OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, tvItem);
1577 * Bug in Windows. When TVM_SETITEM is used to set
1578 * the state image of an item inside TVN_GETDISPINFO,
1579 * the new state is not redrawn. The fix is to force
1582 if ((parent.style & SWT.VIRTUAL) != 0) {
1583 if (parent.currentItem == this && OS.IsWindowVisible (hwnd)) {
1584 RECT rect = new RECT ();
1585 if (OS.TreeView_GetItemRect (hwnd, handle, rect, false)) {
1586 OS.InvalidateRect (hwnd, rect, true);
1593 * Sets the image for multiple columns in the tree.
1595 * @param images the array of new images
1597 * @exception IllegalArgumentException <ul>
1598 * <li>ERROR_NULL_ARGUMENT - if the array of images is null</li>
1599 * <li>ERROR_INVALID_ARGUMENT - if one of the images has been disposed</li>
1601 * @exception SWTException <ul>
1602 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1603 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1608 public void setImage (Image [] images) {
1610 if (images == null) error (SWT.ERROR_NULL_ARGUMENT);
1611 for (int i=0; i<images.length; i++) {
1612 setImage (i, images [i]);
1617 * Sets the receiver's image at a column.
1619 * @param index the column index
1620 * @param image the new image
1622 * @exception IllegalArgumentException <ul>
1623 * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
1625 * @exception SWTException <ul>
1626 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1627 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1632 public void setImage (int index, Image image) {
1634 if (image != null && image.isDisposed ()) {
1635 error(SWT.ERROR_INVALID_ARGUMENT);
1637 Image oldImage = null;
1639 if (image != null && image.type == SWT.ICON) {
1640 if (image.equals (this.image)) return;
1642 oldImage = this.image;
1643 super.setImage (image);
1645 int count = Math.max (1, parent.getColumnCount ());
1646 if (0 > index || index > count - 1) return;
1647 if (images == null && index != 0) {
1648 images = new Image [count];
1651 if (images != null) {
1652 if (image != null && image.type == SWT.ICON) {
1653 if (image.equals (images [index])) return;
1655 oldImage = images [index];
1656 images [index] = image;
1658 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
1660 /* Ensure that the image list is created */
1661 //TODO - items that are not in column zero don't need to be in the image list
1662 parent.imageIndex (image, index);
1665 if ((parent.style & SWT.VIRTUAL) == 0 &&!cached && !parent.painted) {
1668 long hwnd = parent.handle;
1669 TVITEM tvItem = new TVITEM ();
1670 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_IMAGE | OS.TVIF_SELECTEDIMAGE;
1671 tvItem.hItem = handle;
1672 tvItem.iImage = tvItem.iSelectedImage = OS.I_IMAGECALLBACK;
1674 * Bug in Windows. When I_IMAGECALLBACK is used with TVM_SETITEM
1675 * to indicate that an image has changed, Windows does not draw
1676 * the new image. The fix is to use LPSTR_TEXTCALLBACK to force
1677 * Windows to ask for the text, causing Windows to ask for both.
1679 tvItem.mask |= OS.TVIF_TEXT;
1680 tvItem.pszText = OS.LPSTR_TEXTCALLBACK;
1681 OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, tvItem);
1683 boolean drawText = (image == null && oldImage != null) || (image != null && oldImage == null);
1684 redraw (index, drawText, true);
1689 public void setImage (Image image) {
1691 setImage (0, image);
1695 * Sets the number of child items contained in the receiver.
1697 * @param count the number of items
1699 * @exception SWTException <ul>
1700 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1701 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1706 public void setItemCount (int count) {
1708 count = Math.max (0, count);
1709 long hwnd = parent.handle;
1710 long hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
1711 parent.setItemCount (count, handle, hItem);
1715 * Sets the text for multiple columns in the tree.
1717 * Note: If control characters like '\n', '\t' etc. are used
1718 * in the string, then the behavior is platform dependent.
1720 * @param strings the array of new strings
1722 * @exception IllegalArgumentException <ul>
1723 * <li>ERROR_NULL_ARGUMENT - if the text is null</li>
1725 * @exception SWTException <ul>
1726 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1727 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1732 public void setText (String [] strings) {
1734 if (strings == null) error (SWT.ERROR_NULL_ARGUMENT);
1735 for (int i=0; i<strings.length; i++) {
1736 String string = strings [i];
1737 if (string != null) setText (i, string);
1742 * Sets the receiver's text at a column
1744 * Note: If control characters like '\n', '\t' etc. are used
1745 * in the string, then the behavior is platform dependent.
1747 * @param index the column index
1748 * @param string the new text
1750 * @exception IllegalArgumentException <ul>
1751 * <li>ERROR_NULL_ARGUMENT - if the text is null</li>
1753 * @exception SWTException <ul>
1754 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1755 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1760 public void setText (int index, String string) {
1762 if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
1764 if (string.equals (text)) return;
1765 super.setText (string);
1767 int count = Math.max (1, parent.getColumnCount ());
1768 if (0 > index || index > count - 1) return;
1769 if (strings == null && index != 0) {
1770 strings = new String [count];
1773 if (strings != null) {
1774 if (string.equals (strings [index])) return;
1775 strings [index] = string;
1777 if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
1779 if ((parent.style & SWT.VIRTUAL) == 0 && !cached && !parent.painted) {
1782 long hwnd = parent.handle;
1783 TVITEM tvItem = new TVITEM ();
1784 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_TEXT;
1785 tvItem.hItem = handle;
1786 tvItem.pszText = OS.LPSTR_TEXTCALLBACK;
1787 OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, tvItem);
1789 redraw (index, true, false);
1794 public void setText (String string) {
1796 setText (0, string);
1799 /*public*/ void sort () {
1801 if ((parent.style & SWT.VIRTUAL) != 0) return;
1802 parent.sort (handle, false);