comparison org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/TreeItem.d @ 0:6dd524f61e62

add dwt win and basic java stuff
author Frank Benoit <benoit@tionex.de>
date Mon, 02 Mar 2009 14:44:16 +0100
parents
children 2e09b0e6857a
comparison
equal deleted inserted replaced
-1:000000000000 0:6dd524f61e62
1 /*******************************************************************************
2 * Copyright (c) 2000, 2008 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13 module org.eclipse.swt.widgets.TreeItem;
14
15 import org.eclipse.swt.SWT;
16 import org.eclipse.swt.SWTException;
17 import org.eclipse.swt.graphics.Color;
18 import org.eclipse.swt.graphics.Font;
19 import org.eclipse.swt.graphics.Image;
20 import org.eclipse.swt.graphics.Point;
21 import org.eclipse.swt.graphics.Rectangle;
22 import org.eclipse.swt.internal.win32.OS;
23
24 import org.eclipse.swt.widgets.Item;
25 import org.eclipse.swt.widgets.Widget;
26 import org.eclipse.swt.widgets.Tree;
27 import org.eclipse.swt.widgets.Event;
28
29 import java.lang.all;
30
31 /**
32 * Instances of this class represent a selectable user interface object
33 * that represents a hierarchy of tree items in a tree widget.
34 *
35 * <dl>
36 * <dt><b>Styles:</b></dt>
37 * <dd>(none)</dd>
38 * <dt><b>Events:</b></dt>
39 * <dd>(none)</dd>
40 * </dl>
41 * <p>
42 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
43 * </p>
44 *
45 * @see <a href="http://www.eclipse.org/swt/snippets/#tree">Tree, TreeItem, TreeColumn snippets</a>
46 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
47 */
48
49 public class TreeItem : Item {
50 /**
51 * the handle to the OS resource
52 * (Warning: This field is platform dependent)
53 * <p>
54 * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
55 * public API. It is marked public only so that it can be shared
56 * within the packages provided by SWT. It is not available on all
57 * platforms and should never be accessed from application code.
58 * </p>
59 */
60 public HANDLE handle;
61 Tree parent;
62 String [] strings;
63 Image [] images;
64 Font font;
65 Font [] cellFont;
66 bool cached;
67 int background = -1, foreground = -1;
68 int [] cellBackground, cellForeground;
69
70 /**
71 * Constructs a new instance of this class given its parent
72 * (which must be a <code>Tree</code> or a <code>TreeItem</code>)
73 * and a style value describing its behavior and appearance.
74 * The item is added to the end of the items maintained by its parent.
75 * <p>
76 * The style value is either one of the style constants defined in
77 * class <code>SWT</code> which is applicable to instances of this
78 * class, or must be built by <em>bitwise OR</em>'ing together
79 * (that is, using the <code>int</code> "|" operator) two or more
80 * of those <code>SWT</code> style constants. The class description
81 * lists the style constants that are applicable to the class.
82 * Style bits are also inherited from superclasses.
83 * </p>
84 *
85 * @param parent a tree control which will be the parent of the new instance (cannot be null)
86 * @param style the style of control to construct
87 *
88 * @exception IllegalArgumentException <ul>
89 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
90 * </ul>
91 * @exception SWTException <ul>
92 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
93 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
94 * </ul>
95 *
96 * @see SWT
97 * @see Widget#checkSubclass
98 * @see Widget#getStyle
99 */
100 public this (Tree parent, int style) {
101 this (parent, style, cast(HANDLE)OS.TVGN_ROOT, cast(HANDLE)OS.TVI_LAST, null);
102 }
103
104 /**
105 * Constructs a new instance of this class given its parent
106 * (which must be a <code>Tree</code> or a <code>TreeItem</code>),
107 * a style value describing its behavior and appearance, and the index
108 * at which to place it in the items maintained by its parent.
109 * <p>
110 * The style value is either one of the style constants defined in
111 * class <code>SWT</code> which is applicable to instances of this
112 * class, or must be built by <em>bitwise OR</em>'ing together
113 * (that is, using the <code>int</code> "|" operator) two or more
114 * of those <code>SWT</code> style constants. The class description
115 * lists the style constants that are applicable to the class.
116 * Style bits are also inherited from superclasses.
117 * </p>
118 *
119 * @param parent a tree control which will be the parent of the new instance (cannot be null)
120 * @param style the style of control to construct
121 * @param index the zero-relative index to store the receiver in its parent
122 *
123 * @exception IllegalArgumentException <ul>
124 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
125 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
126 * </ul>
127 * @exception SWTException <ul>
128 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
129 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
130 * </ul>
131 *
132 * @see SWT
133 * @see Widget#checkSubclass
134 * @see Widget#getStyle
135 */
136 public this (Tree parent, int style, int index) {
137 this (parent, style, cast(HANDLE) OS.TVGN_ROOT, findPrevious (parent, index), null);
138 }
139
140 /**
141 * Constructs a new instance of this class given its parent
142 * (which must be a <code>Tree</code> or a <code>TreeItem</code>)
143 * and a style value describing its behavior and appearance.
144 * The item is added to the end of the items maintained by its parent.
145 * <p>
146 * The style value is either one of the style constants defined in
147 * class <code>SWT</code> which is applicable to instances of this
148 * class, or must be built by <em>bitwise OR</em>'ing together
149 * (that is, using the <code>int</code> "|" operator) two or more
150 * of those <code>SWT</code> style constants. The class description
151 * lists the style constants that are applicable to the class.
152 * Style bits are also inherited from superclasses.
153 * </p>
154 *
155 * @param parentItem a tree control which will be the parent of the new instance (cannot be null)
156 * @param style the style of control to construct
157 *
158 * @exception IllegalArgumentException <ul>
159 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
160 * </ul>
161 * @exception SWTException <ul>
162 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
163 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
164 * </ul>
165 *
166 * @see SWT
167 * @see Widget#checkSubclass
168 * @see Widget#getStyle
169 */
170 public this (TreeItem parentItem, int style) {
171 this (checkNull (parentItem).parent, style, parentItem.handle, cast(HANDLE)OS.TVI_LAST, null);
172 }
173
174 /**
175 * Constructs a new instance of this class given its parent
176 * (which must be a <code>Tree</code> or a <code>TreeItem</code>),
177 * a style value describing its behavior and appearance, and the index
178 * at which to place it in the items maintained by its parent.
179 * <p>
180 * The style value is either one of the style constants defined in
181 * class <code>SWT</code> which is applicable to instances of this
182 * class, or must be built by <em>bitwise OR</em>'ing together
183 * (that is, using the <code>int</code> "|" operator) two or more
184 * of those <code>SWT</code> style constants. The class description
185 * lists the style constants that are applicable to the class.
186 * Style bits are also inherited from superclasses.
187 * </p>
188 *
189 * @param parentItem a tree control which will be the parent of the new instance (cannot be null)
190 * @param style the style of control to construct
191 * @param index the zero-relative index to store the receiver in its parent
192 *
193 * @exception IllegalArgumentException <ul>
194 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
195 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
196 * </ul>
197 * @exception SWTException <ul>
198 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
199 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
200 * </ul>
201 *
202 * @see SWT
203 * @see Widget#checkSubclass
204 * @see Widget#getStyle
205 */
206 public this (TreeItem parentItem, int style, int index) {
207 this (checkNull (parentItem).parent, style, parentItem.handle, findPrevious (parentItem, index), null);
208 }
209
210 this (Tree parent, int style, HANDLE hParent, HANDLE hInsertAfter, HANDLE hItem) {
211 super (parent, style);
212 this.parent = parent;
213 parent.createItem (this, hParent, hInsertAfter, hItem);
214 }
215
216 static TreeItem checkNull (TreeItem item) {
217 if (item is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
218 return item;
219 }
220
221 static HANDLE findPrevious (Tree parent, int index) {
222 if (parent is null) return null;
223 if (index < 0) SWT.error (SWT.ERROR_INVALID_RANGE);
224 if (index is 0) return cast(HANDLE) OS.TVI_FIRST;
225 auto hwnd = parent.handle;
226 HANDLE hFirstItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
227 HANDLE hItem = parent.findItem (hFirstItem, index - 1);
228 if (hItem is null) SWT.error (SWT.ERROR_INVALID_RANGE);
229 return hItem;
230 }
231
232 static HANDLE findPrevious (TreeItem parentItem, int index) {
233 if (parentItem is null) return null;
234 if (index < 0) SWT.error (SWT.ERROR_INVALID_RANGE);
235 if (index is 0) return cast(HANDLE) OS.TVI_FIRST;
236 Tree parent = parentItem.parent;
237 auto hwnd = parent.handle;
238 auto hParent = parentItem.handle;
239 HANDLE hFirstItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hParent);
240 HANDLE hItem = parent.findItem (hFirstItem, index - 1);
241 if (hItem is null) SWT.error (SWT.ERROR_INVALID_RANGE);
242 return hItem;
243 }
244
245 override protected void checkSubclass () {
246 if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
247 }
248
249 void clear () {
250 text = "";
251 image = null;
252 strings = null;
253 images = null;
254 if ((parent.style & SWT.CHECK) !is 0) {
255 auto hwnd = parent.handle;
256 TVITEM tvItem;
257 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
258 tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
259 tvItem.state = 1 << 12;
260 tvItem.hItem = cast(HTREEITEM)handle;
261 OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, &tvItem);
262 }
263 background = foreground = -1;
264 font = null;
265 cellBackground = cellForeground = null;
266 cellFont = null;
267 if ((parent.style & SWT.VIRTUAL) !is 0) cached = false;
268 }
269
270 /**
271 * Clears the item at the given zero-relative index in the receiver.
272 * The text, icon and other attributes of the item are set to the default
273 * value. If the tree was created with the <code>SWT.VIRTUAL</code> style,
274 * these attributes are requested again as needed.
275 *
276 * @param index the index of the item to clear
277 * @param all <code>true</code> if all child items of the indexed item should be
278 * cleared recursively, and <code>false</code> otherwise
279 *
280 * @exception IllegalArgumentException <ul>
281 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
282 * </ul>
283 * @exception SWTException <ul>
284 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
285 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
286 * </ul>
287 *
288 * @see SWT#VIRTUAL
289 * @see SWT#SetData
290 *
291 * @since 3.2
292 */
293 public void clear (int index, bool all) {
294 checkWidget ();
295 auto hwnd = parent.handle;
296 HANDLE hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
297 if (hItem is null) error (SWT.ERROR_INVALID_RANGE);
298 hItem = parent.findItem (hItem, index);
299 if (hItem is null) error (SWT.ERROR_INVALID_RANGE);
300 TVITEM tvItem;
301 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
302 parent.clear (hItem, &tvItem);
303 if (all) {
304 hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
305 parent.clearAll (hItem, &tvItem, all);
306 }
307 }
308
309 /**
310 * Clears all the items in the receiver. The text, icon and other
311 * attributes of the items are set to their default values. If the
312 * tree was created with the <code>SWT.VIRTUAL</code> style, these
313 * attributes are requested again as needed.
314 *
315 * @param all <code>true</code> if all child items should be cleared
316 * recursively, and <code>false</code> otherwise
317 *
318 * @exception SWTException <ul>
319 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
320 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
321 * </ul>
322 *
323 * @see SWT#VIRTUAL
324 * @see SWT#SetData
325 *
326 * @since 3.2
327 */
328 public void clearAll (bool all) {
329 checkWidget ();
330 auto hwnd = parent.handle;
331 auto hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
332 if (hItem is null) return;
333 TVITEM tvItem;
334 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
335 parent.clearAll (hItem, &tvItem, all);
336 }
337
338 override void destroyWidget () {
339 TVITEM tvItem;
340 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
341 parent.releaseItem (handle, &tvItem, false);
342 parent.destroyItem (this, handle);
343 releaseHandle ();
344 }
345
346 HFONT fontHandle (int index) {
347 if (cellFont !is null && cellFont [index] !is null) return cellFont [index].handle;
348 if (font !is null) return font.handle;
349 return cast(HFONT)-1;
350 }
351
352 /**
353 * Returns the receiver's background color.
354 *
355 * @return the background color
356 *
357 * @exception SWTException <ul>
358 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
359 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
360 * </ul>
361 *
362 * @since 2.0
363 *
364 */
365 public Color getBackground () {
366 checkWidget ();
367 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
368 if (background is -1) return parent.getBackground ();
369 return Color.win32_new (display, background);
370 }
371
372 /**
373 * Returns the background color at the given column index in the receiver.
374 *
375 * @param index the column index
376 * @return the background color
377 *
378 * @exception SWTException <ul>
379 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
380 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
381 * </ul>
382 *
383 * @since 3.1
384 */
385 public Color getBackground (int index) {
386 checkWidget ();
387 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
388 int count = Math.max (1, parent.getColumnCount ());
389 if (0 > index || index > count - 1) return getBackground ();
390 int pixel = cellBackground !is null ? cellBackground [index] : -1;
391 return pixel is -1 ? getBackground () : Color.win32_new (display, pixel);
392 }
393
394 /**
395 * Returns a rectangle describing the receiver's size and location
396 * relative to its parent.
397 *
398 * @return the receiver's bounding rectangle
399 *
400 * @exception SWTException <ul>
401 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
402 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
403 * </ul>
404 */
405 public Rectangle getBounds () {
406 checkWidget ();
407 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
408 RECT* rect = getBounds (0, true, false, false);
409 int width = rect.right - rect.left, height = rect.bottom - rect.top;
410 return new Rectangle (rect.left, rect.top, width, height);
411 }
412
413 /**
414 * Returns a rectangle describing the receiver's size and location
415 * relative to its parent at a column in the tree.
416 *
417 * @param index the index that specifies the column
418 * @return the receiver's bounding column rectangle
419 *
420 * @exception SWTException <ul>
421 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
422 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
423 * </ul>
424 *
425 * @since 3.1
426 */
427 public Rectangle getBounds (int index) {
428 checkWidget();
429 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
430 RECT* rect = getBounds (index, true, true, true);
431 int width = rect.right - rect.left, height = rect.bottom - rect.top;
432 return new Rectangle (rect.left, rect.top, width, height);
433 }
434
435 RECT* getBounds (int index, bool getText, bool getImage, bool fullText) {
436 return getBounds (index, getText, getImage, fullText, false, true, null);
437 }
438
439 //TODO - take into account grid (add bool arg) to damage less during redraw
440 RECT* getBounds (int index, bool getText, bool getImage, bool fullText, bool fullImage, bool clip, HDC hDC) {
441 if (!getText && !getImage) return new RECT();
442 auto hwnd = parent.handle;
443 if ((parent.style & SWT.VIRTUAL) is 0 && !cached && !parent.painted) {
444 TVITEM tvItem;
445 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_TEXT;
446 tvItem.hItem = cast(HTREEITEM)handle;
447 tvItem.pszText = OS.LPSTR_TEXTCALLBACK;
448 parent.ignoreCustomDraw = true;
449 OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, &tvItem);
450 parent.ignoreCustomDraw = false;
451 }
452 bool firstColumn = index is 0;
453 int columnCount = 0;
454 auto hwndHeader = parent.hwndHeader;
455 if (hwndHeader !is null) {
456 columnCount = parent.columnCount;
457 firstColumn = index is OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
458 }
459 RECT* rect = new RECT();
460 if (firstColumn) {
461 bool full = columnCount is 0 && getText && getImage && fullText && fullImage;
462 if (!OS.TreeView_GetItemRect (hwnd, cast(HTREEITEM)handle, rect, !full)) {
463 return new RECT();
464 }
465 if (getImage && !fullImage) {
466 if (OS.SendMessage (hwnd, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0) !is 0) {
467 Point size = parent.getImageSize ();
468 rect.left -= size.x + Tree.INSET;
469 if (!getText) rect.right = rect.left + size.x;
470 } else {
471 if (!getText) rect.right = rect.left;
472 }
473 }
474 if (fullText || fullImage || clip) {
475 if (hwndHeader !is null) {
476 RECT* headerRect = new RECT();
477 if (columnCount !is 0) {
478 if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, cast(int) headerRect) is 0) {
479 return new RECT();
480 }
481 } else {
482 headerRect.right = parent.scrollWidth;
483 if (headerRect.right is 0) headerRect = rect;
484 }
485 if (fullText && clip) rect.right = headerRect.right;
486 if (fullImage) rect.left = headerRect.left;
487 if (clip && headerRect.right < rect.right) {
488 rect.right = headerRect.right;
489 }
490 }
491 }
492 } else {
493 if (!(0 <= index && index < columnCount)) return new RECT();
494 RECT* headerRect = new RECT();
495 if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, cast(int) headerRect) is 0) {
496 return new RECT();
497 }
498 if (!OS.TreeView_GetItemRect (hwnd, cast(HTREEITEM)handle, rect, false)) {
499 return new RECT();
500 }
501 rect.left = headerRect.left;
502 if (fullText && getImage && clip) {
503 rect.right = headerRect.right;
504 } else {
505 rect.right = headerRect.left;
506 Image image = null;
507 if (index is 0) {
508 image = this.image;
509 } else {
510 if (images !is null) image = images [index];
511 }
512 if (image !is null) {
513 Point size = parent.getImageSize ();
514 rect.right += size.x;
515 }
516 if (getText) {
517 if (fullText && clip) {
518 rect.left = rect.right + Tree.INSET;
519 rect.right = headerRect.right;
520 } else {
521 String string = index is 0 ? text : strings !is null ? strings [index] : null;
522 if (string !is null) {
523 RECT* textRect = new RECT();
524 TCHAR[] buffer = StrToTCHARs (parent.getCodePage (), string, false);
525 int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_CALCRECT;
526 auto hNewDC = hDC;
527 HFONT hFont;
528 if (hDC is null) {
529 hNewDC = OS.GetDC (hwnd);
530 hFont = fontHandle (index);
531 if (hFont is cast(HFONT)-1) hFont = cast(HFONT) OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
532 hFont = OS.SelectObject (hNewDC, hFont);
533 }
534 OS.DrawText (hNewDC, buffer.ptr, buffer.length, textRect, flags);
535 if (hDC is null) {
536 OS.SelectObject (hNewDC, hFont);
537 OS.ReleaseDC (hwnd, hNewDC);
538 }
539 if (getImage) {
540 rect.right += textRect.right - textRect.left + Tree.INSET * 3;
541 } else {
542 rect.left = rect.right + Tree.INSET;
543 rect.right = rect.left + (textRect.right - textRect.left) + Tree.INSET;
544 }
545 }
546 }
547 }
548 if (clip && headerRect.right < rect.right) {
549 rect.right = headerRect.right;
550 }
551 }
552 }
553 int gridWidth = parent.linesVisible && columnCount !is 0 ? Tree.GRID_WIDTH : 0;
554 if (getText || !getImage) {
555 rect.right = Math.max (rect.left, rect.right - gridWidth);
556 }
557 rect.bottom = Math.max (rect.top, rect.bottom - gridWidth);
558 return rect;
559 }
560
561 /**
562 * Returns <code>true</code> if the receiver is checked,
563 * and false otherwise. When the parent does not have
564 * the <code>CHECK style, return false.
565 * <p>
566 *
567 * @return the checked state
568 *
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>
572 * </ul>
573 */
574 public bool getChecked () {
575 checkWidget ();
576 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
577 if ((parent.style & SWT.CHECK) is 0) return false;
578 auto hwnd = parent.handle;
579 TVITEM tvItem;
580 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
581 tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
582 tvItem.hItem = cast(HTREEITEM)handle;
583 int result = OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, &tvItem);
584 return (result !is 0) && (((tvItem.state >> 12) & 1) is 0);
585 }
586
587 /**
588 * Returns <code>true</code> if the receiver is expanded,
589 * and false otherwise.
590 * <p>
591 *
592 * @return the expanded state
593 *
594 * @exception SWTException <ul>
595 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
596 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
597 * </ul>
598 */
599 public bool getExpanded () {
600 checkWidget ();
601 auto hwnd = parent.handle;
602 int state = 0;
603 static if (OS.IsWinCE) {
604 TVITEM tvItem;
605 tvItem.hItem = handle;
606 tvItem.mask = OS.TVIF_STATE;
607 OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, &tvItem);
608 state = tvItem.state;
609 } else {
610 /*
611 * Bug in Windows. Despite the fact that TVM_GETITEMSTATE claims
612 * to return only the bits specified by the stateMask, when called
613 * with TVIS_EXPANDED, the entire state is returned. The fix is
614 * to explicitly check for the TVIS_EXPANDED bit.
615 */
616 state = OS.SendMessage (hwnd, OS.TVM_GETITEMSTATE, handle, OS.TVIS_EXPANDED);
617 }
618 return (state & OS.TVIS_EXPANDED) !is 0;
619 }
620
621 /**
622 * Returns the font that the receiver will use to paint textual information for this item.
623 *
624 * @return the receiver's font
625 *
626 * @exception SWTException <ul>
627 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
628 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
629 * </ul>
630 *
631 * @since 3.0
632 */
633 public Font getFont () {
634 checkWidget ();
635 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
636 return font !is null ? font : parent.getFont ();
637 }
638
639 /**
640 * Returns the font that the receiver will use to paint textual information
641 * for the specified cell in this item.
642 *
643 * @param index the column index
644 * @return the receiver's font
645 *
646 * @exception SWTException <ul>
647 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
648 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
649 * </ul>
650 *
651 * @since 3.1
652 */
653 public Font getFont (int index) {
654 checkWidget ();
655 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
656 int count = Math.max (1, parent.getColumnCount ());
657 if (0 > index || index > count -1) return getFont ();
658 if (cellFont is null || cellFont [index] is null) return getFont ();
659 return cellFont [index];
660 }
661
662 /**
663 * Returns the foreground color that the receiver will use to draw.
664 *
665 * @return the receiver's foreground color
666 *
667 * @exception SWTException <ul>
668 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
669 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
670 * </ul>
671 *
672 * @since 2.0
673 *
674 */
675 public Color getForeground () {
676 checkWidget ();
677 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
678 if (foreground is -1) return parent.getForeground ();
679 return Color.win32_new (display, foreground);
680 }
681
682 /**
683 *
684 * Returns the foreground color at the given column index in the receiver.
685 *
686 * @param index the column index
687 * @return the foreground color
688 *
689 * @exception SWTException <ul>
690 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
691 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
692 * </ul>
693 *
694 * @since 3.1
695 */
696 public Color getForeground (int index) {
697 checkWidget ();
698 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
699 int count = Math.max (1, parent.getColumnCount ());
700 if (0 > index || index > count -1) return getForeground ();
701 int pixel = cellForeground !is null ? cellForeground [index] : -1;
702 return pixel is -1 ? getForeground () : Color.win32_new (display, pixel);
703 }
704
705 /**
706 * Returns <code>true</code> if the receiver is grayed,
707 * and false otherwise. When the parent does not have
708 * the <code>CHECK style, return false.
709 * <p>
710 *
711 * @return the grayed state of the checkbox
712 *
713 * @exception SWTException <ul>
714 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
715 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
716 * </ul>
717 */
718 public bool getGrayed () {
719 checkWidget ();
720 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
721 if ((parent.style & SWT.CHECK) is 0) return false;
722 auto hwnd = parent.handle;
723 TVITEM tvItem;
724 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
725 tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
726 tvItem.hItem = cast(HTREEITEM)handle;
727 int result = OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, &tvItem);
728 return (result !is 0) && ((tvItem.state >> 12) > 2);
729 }
730
731 /**
732 * Returns the item at the given, zero-relative index in the
733 * receiver. Throws an exception if the index is out of range.
734 *
735 * @param index the index of the item to return
736 * @return the item at the given index
737 *
738 * @exception IllegalArgumentException <ul>
739 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
740 * </ul>
741 * @exception SWTException <ul>
742 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
743 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
744 * </ul>
745 *
746 * @since 3.1
747 */
748 public TreeItem getItem (int index) {
749 checkWidget ();
750 if (index < 0) error (SWT.ERROR_INVALID_RANGE);
751 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
752 auto hwnd = parent.handle;
753 auto hFirstItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
754 if (hFirstItem is null) error (SWT.ERROR_INVALID_RANGE);
755 auto hItem = parent.findItem (hFirstItem, index);
756 if (hItem is null) error (SWT.ERROR_INVALID_RANGE);
757 return parent._getItem (hItem);
758 }
759
760 /**
761 * Returns the number of items contained in the receiver
762 * that are direct item children of the receiver.
763 *
764 * @return the number of items
765 *
766 * @exception SWTException <ul>
767 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
768 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
769 * </ul>
770 */
771 public int getItemCount () {
772 checkWidget ();
773 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
774 auto hwnd = parent.handle;
775 auto hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
776 if (hItem is null) return 0;
777 return parent.getItemCount (hItem);
778 }
779
780 /**
781 * Returns a (possibly empty) array of <code>TreeItem</code>s which
782 * are the direct item children of the receiver.
783 * <p>
784 * Note: This is not the actual structure used by the receiver
785 * to maintain its list of items, so modifying the array will
786 * not affect the receiver.
787 * </p>
788 *
789 * @return the receiver's items
790 *
791 * @exception SWTException <ul>
792 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
793 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
794 * </ul>
795 */
796 public TreeItem [] getItems () {
797 checkWidget ();
798 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
799 auto hwnd = parent.handle;
800 auto hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
801 if (hItem is null) return null;
802 return parent.getItems (hItem);
803 }
804
805 override public Image getImage () {
806 checkWidget();
807 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
808 return super.getImage ();
809 }
810
811 /**
812 * Returns the image stored at the given column index in the receiver,
813 * or null if the image has not been set or if the column does not exist.
814 *
815 * @param index the column index
816 * @return the image stored at the given column index in the receiver
817 *
818 * @exception SWTException <ul>
819 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
820 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
821 * </ul>
822 *
823 * @since 3.1
824 */
825 public Image getImage (int index) {
826 checkWidget();
827 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
828 if (index is 0) return getImage ();
829 if (images !is null) {
830 if (0 <= index && index < images.length) return images [index];
831 }
832 return null;
833 }
834
835 /**
836 * Returns a rectangle describing the size and location
837 * relative to its parent of an image at a column in the
838 * tree.
839 *
840 * @param index the index that specifies the column
841 * @return the receiver's bounding image rectangle
842 *
843 * @exception SWTException <ul>
844 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
845 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
846 * </ul>
847 *
848 * @since 3.1
849 */
850 public Rectangle getImageBounds (int index) {
851 checkWidget();
852 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
853 RECT* rect = getBounds (index, false, true, false);
854 int width = rect.right - rect.left, height = rect.bottom - rect.top;
855 return new Rectangle (rect.left, rect.top, width, height);
856 }
857
858 /**
859 * Returns the receiver's parent, which must be a <code>Tree</code>.
860 *
861 * @return the receiver's parent
862 *
863 * @exception SWTException <ul>
864 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
865 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
866 * </ul>
867 */
868 public Tree getParent () {
869 checkWidget ();
870 return parent;
871 }
872
873 /**
874 * Returns the receiver's parent item, which must be a
875 * <code>TreeItem</code> or null when the receiver is a
876 * root.
877 *
878 * @return the receiver's parent item
879 *
880 * @exception SWTException <ul>
881 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
882 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
883 * </ul>
884 */
885 public TreeItem getParentItem () {
886 checkWidget ();
887 auto hwnd = parent.handle;
888 auto hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, handle);
889 return hItem !is null ? parent._getItem (hItem) : null;
890 }
891
892 override public String getText () {
893 checkWidget();
894 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
895 return super.getText ();
896 }
897
898 /**
899 * Returns the text stored at the given column index in the receiver,
900 * or empty string if the text has not been set.
901 *
902 * @param index the column index
903 * @return the text stored at the given column index in the receiver
904 *
905 * @exception SWTException <ul>
906 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
907 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
908 * </ul>
909 *
910 * @since 3.1
911 */
912 public String getText (int index) {
913 checkWidget();
914 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
915 if (index is 0) return getText ();
916 if (strings !is null) {
917 if (0 <= index && index < strings.length) {
918 String string = strings [index];
919 return string !is null ? string : "";
920 }
921 }
922 return "";
923 }
924
925 /**
926 * Returns a rectangle describing the size and location
927 * relative to its parent of the text at a column in the
928 * tree.
929 *
930 * @param index the index that specifies the column
931 * @return the receiver's bounding text rectangle
932 *
933 * @exception SWTException <ul>
934 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
935 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
936 * </ul>
937 *
938 * @since 3.3
939 */
940 public Rectangle getTextBounds (int index) {
941 checkWidget();
942 if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
943 RECT* rect = getBounds (index, true, false, true);
944 if (index is 0) rect.left += Tree.INSET - 1;
945 rect.left = Math.min (rect.left, rect.right);
946 rect.right = rect.right - Tree.INSET;
947 int width = Math.max (0, rect.right - rect.left);
948 int height = Math.max (0, rect.bottom - rect.top);
949 return new Rectangle (rect.left, rect.top, width, height);
950 }
951
952 /**
953 * Searches the receiver's list starting at the first item
954 * (index 0) until an item is found that is equal to the
955 * argument, and returns the index of that item. If no item
956 * is found, returns -1.
957 *
958 * @param item the search item
959 * @return the index of the item
960 *
961 * @exception IllegalArgumentException <ul>
962 * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
963 * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li>
964 * </ul>
965 * @exception SWTException <ul>
966 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
967 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
968 * </ul>
969 *
970 * @since 3.1
971 */
972 public int indexOf (TreeItem item) {
973 checkWidget ();
974 if (item is null) error (SWT.ERROR_NULL_ARGUMENT);
975 if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
976 auto hwnd = parent.handle;
977 auto hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
978 return hItem is null ? -1 : parent.findIndex (hItem, item.handle);
979 }
980
981 void redraw () {
982 if (parent.currentItem is this || parent.drawCount !is 0) return;
983 auto hwnd = parent.handle;
984 if (!OS.IsWindowVisible (hwnd)) return;
985 /*
986 * When there are no columns and the tree is not
987 * full selection, redraw only the text. This is
988 * an optimization to reduce flashing.
989 */
990 bool full = (parent.style & (SWT.FULL_SELECTION | SWT.VIRTUAL)) !is 0;
991 if (!full) {
992 full = parent.columnCount !is 0;
993 if (!full) {
994 if (parent.hooks (SWT.EraseItem) || parent.hooks (SWT.PaintItem)) {
995 full = true;
996 }
997 }
998 }
999 RECT rect;
1000 if (OS.TreeView_GetItemRect (hwnd, cast(HTREEITEM)handle, &rect, !full)) {
1001 OS.InvalidateRect (hwnd, &rect, true);
1002 }
1003 }
1004
1005 void redraw (int column, bool drawText, bool drawImage) {
1006 if (parent.currentItem is this || parent.drawCount !is 0) return;
1007 auto hwnd = parent.handle;
1008 if (!OS.IsWindowVisible (hwnd)) return;
1009 bool fullImage = column is 0 && drawText && drawImage;
1010 RECT* rect = getBounds (column, drawText, drawImage, true, fullImage, true, null);
1011 OS.InvalidateRect (hwnd, rect, true);
1012 }
1013
1014 override void releaseChildren (bool destroy) {
1015 if (destroy) {
1016 TVITEM tvItem;
1017 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
1018 parent.releaseItems (handle, &tvItem);
1019 }
1020 super.releaseChildren (destroy);
1021 }
1022
1023 override void releaseHandle () {
1024 super.releaseHandle ();
1025 handle = null;
1026 parent = null;
1027 }
1028
1029 override void releaseWidget () {
1030 super.releaseWidget ();
1031 strings = null;
1032 images = null;
1033 cellBackground = cellForeground = null;
1034 cellFont = null;
1035 }
1036
1037 /**
1038 * Removes all of the items from the receiver.
1039 * <p>
1040 * @exception SWTException <ul>
1041 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1042 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1043 * </ul>
1044 *
1045 * @since 3.1
1046 */
1047 public void removeAll () {
1048 checkWidget ();
1049 auto hwnd = parent.handle;
1050 TVITEM tvItem;
1051 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
1052 tvItem.hItem = cast(HTREEITEM) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, cast(int)handle);
1053 while (tvItem.hItem !is null) {
1054 OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, cast(int)&tvItem);
1055 TreeItem item = tvItem.lParam !is -1 ? parent.items [tvItem.lParam] : null;
1056 if (item !is null && !item.isDisposed ()) {
1057 item.dispose ();
1058 } else {
1059 parent.releaseItem (tvItem.hItem, &tvItem, false);
1060 parent.destroyItem (null, tvItem.hItem);
1061 }
1062 tvItem.hItem = cast(HTREEITEM) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, cast(int)handle);
1063 }
1064 }
1065
1066 /**
1067 * Sets the receiver's background color to the color specified
1068 * by the argument, or to the default system color for the item
1069 * if the argument is null.
1070 *
1071 * @param color the new color (or null)
1072 *
1073 * @exception IllegalArgumentException <ul>
1074 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
1075 * </ul>
1076 * @exception SWTException <ul>
1077 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1078 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1079 * </ul>
1080 *
1081 * @since 2.0
1082 *
1083 */
1084 public void setBackground (Color color) {
1085 checkWidget ();
1086 if (color !is null && color.isDisposed ()) {
1087 SWT.error (SWT.ERROR_INVALID_ARGUMENT);
1088 }
1089 int pixel = -1;
1090 if (color !is null) {
1091 parent.customDraw = true;
1092 pixel = color.handle;
1093 }
1094 if (background is pixel) return;
1095 background = pixel;
1096 if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
1097 redraw ();
1098 }
1099
1100 /**
1101 * Sets the background color at the given column index in the receiver
1102 * to the color specified by the argument, or to the default system color for the item
1103 * if the argument is null.
1104 *
1105 * @param index the column index
1106 * @param color the new color (or null)
1107 *
1108 * @exception IllegalArgumentException <ul>
1109 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
1110 * </ul>
1111 * @exception SWTException <ul>
1112 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1113 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1114 * </ul>
1115 *
1116 * @since 3.1
1117 *
1118 */
1119 public void setBackground (int index, Color color) {
1120 checkWidget ();
1121 if (color !is null && color.isDisposed ()) {
1122 SWT.error (SWT.ERROR_INVALID_ARGUMENT);
1123 }
1124 int count = Math.max (1, parent.getColumnCount ());
1125 if (0 > index || index > count - 1) return;
1126 int pixel = -1;
1127 if (color !is null) {
1128 parent.customDraw = true;
1129 pixel = color.handle;
1130 }
1131 if (cellBackground is null) {
1132 cellBackground = new int [count];
1133 for (int i = 0; i < count; i++) {
1134 cellBackground [i] = -1;
1135 }
1136 }
1137 if (cellBackground [index] is pixel) return;
1138 cellBackground [index] = pixel;
1139 if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
1140 redraw (index, true, true);
1141 }
1142
1143 /**
1144 * Sets the checked state of the receiver.
1145 * <p>
1146 *
1147 * @param checked the new checked state
1148 *
1149 * @exception SWTException <ul>
1150 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1151 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1152 * </ul>
1153 */
1154 public void setChecked (bool checked) {
1155 checkWidget ();
1156 if ((parent.style & SWT.CHECK) is 0) return;
1157 auto hwnd = parent.handle;
1158 TVITEM tvItem;
1159 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
1160 tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
1161 tvItem.hItem = cast(HTREEITEM)handle;
1162 OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, &tvItem);
1163 int state = tvItem.state >> 12;
1164 if (checked) {
1165 if ((state & 0x1) !is 0) state++;
1166 } else {
1167 if ((state & 0x1) is 0) --state;
1168 }
1169 state <<= 12;
1170 if (tvItem.state is state) return;
1171 if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
1172 tvItem.state = state;
1173 OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, &tvItem);
1174 /*
1175 * Bug in Windows. When TVM_SETITEM is used to set
1176 * the state image of an item inside TVN_GETDISPINFO,
1177 * the new state is not redrawn. The fix is to force
1178 * a redraw.
1179 */
1180 if ((parent.style & SWT.VIRTUAL) !is 0) {
1181 if (parent.currentItem is this && OS.IsWindowVisible (hwnd)) {
1182 RECT rect;
1183 if (OS.TreeView_GetItemRect (hwnd, cast(HTREEITEM)handle, &rect, false)) {
1184 OS.InvalidateRect (hwnd, &rect, true);
1185 }
1186 }
1187 }
1188 }
1189
1190 /**
1191 * Sets the expanded state of the receiver.
1192 * <p>
1193 *
1194 * @param expanded the new expanded state
1195 *
1196 * @exception SWTException <ul>
1197 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1198 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1199 * </ul>
1200 */
1201 public void setExpanded (bool expanded) {
1202 checkWidget ();
1203
1204 /* Do nothing when the item is a leaf or already expanded */
1205 auto hwnd = parent.handle;
1206 if (OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle) is 0) {
1207 return;
1208 }
1209 int state = 0;
1210 static if (OS.IsWinCE) {
1211 TVITEM tvItem;
1212 tvItem.hItem = handle;
1213 tvItem.mask = OS.TVIF_STATE;
1214 OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, &tvItem);
1215 state = tvItem.state;
1216 } else {
1217 /*
1218 * Bug in Windows. Despite the fact that TVM_GETITEMSTATE claims
1219 * to return only the bits specified by the stateMask, when called
1220 * with TVIS_EXPANDED, the entire state is returned. The fix is
1221 * to explicitly check for the TVIS_EXPANDED bit.
1222 */
1223 state = OS.SendMessage (hwnd, OS.TVM_GETITEMSTATE, handle, OS.TVIS_EXPANDED);
1224 }
1225 if (((state & OS.TVIS_EXPANDED) !is 0) is expanded) return;
1226
1227 /*
1228 * Feature in Windows. When TVM_EXPAND is used to expand
1229 * an item, the widget scrolls to show the item and the
1230 * newly expanded items. While not strictly incorrect,
1231 * this means that application code that expands tree items
1232 * in a background thread can scroll the widget while the
1233 * user is interacting with it. The fix is to remember
1234 * the top item and the bounds of every tree item, turn
1235 * redraw off, expand the item, scroll back to the top
1236 * item. If none of the rectangles have moved, then
1237 * it is safe to turn redraw back on without redrawing
1238 * the control.
1239 */
1240 RECT oldRect;
1241 RECT [] rects = null;
1242 SCROLLINFO* oldInfo;
1243 int count = 0;
1244 HANDLE hBottomItem;
1245 bool redraw = false, noScroll = true;
1246 HANDLE hTopItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
1247 if (noScroll && hTopItem !is null) {
1248 oldInfo = new SCROLLINFO ();
1249 oldInfo.cbSize = SCROLLINFO.sizeof;
1250 oldInfo.fMask = OS.SIF_ALL;
1251 if (!OS.GetScrollInfo (hwnd, OS.SB_HORZ, oldInfo)) {
1252 oldInfo = null;
1253 }
1254 if (parent.drawCount is 0 && OS.IsWindowVisible (hwnd)) {
1255 bool noAnimate = true;
1256 count = OS.SendMessage (hwnd, OS.TVM_GETVISIBLECOUNT, 0, 0);
1257 rects = new RECT [count + 1];
1258 HANDLE hItem = hTopItem;
1259 int index = 0;
1260 while (hItem !is null && (noAnimate || hItem !is handle) && index < count) {
1261 RECT rect;
1262 if (OS.TreeView_GetItemRect (hwnd, cast(HTREEITEM)hItem, &rect, true)) {
1263 rects [index++] = rect;
1264 }
1265 hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, cast(int) &hItem);
1266 }
1267 if (noAnimate || hItem !is handle) {
1268 redraw = true;
1269 count = index;
1270 hBottomItem = hItem;
1271 //oldRect = new RECT ();
1272 OS.GetClientRect (hwnd, &oldRect);
1273 auto topHandle = parent.topHandle ();
1274 OS.UpdateWindow (topHandle);
1275 OS.DefWindowProc (topHandle, OS.WM_SETREDRAW, 0, 0);
1276 if (hwnd !is topHandle) {
1277 OS.UpdateWindow (hwnd);
1278 OS.DefWindowProc (hwnd, OS.WM_SETREDRAW, 0, 0);
1279 }
1280 /*
1281 * This code is intentionally commented.
1282 */
1283 // OS.SendMessage (hwnd, OS.WM_SETREDRAW, 0, 0);
1284 }
1285 }
1286 }
1287
1288 /*
1289 * Feature in Windows. When the user collapses the root
1290 * of a subtree that has the focus item, Windows moves
1291 * the selection to the root of the subtree and issues
1292 * a TVN_SELCHANGED to inform the programmer that the
1293 * selection has changed. When the programmer collapses
1294 * the same subtree using TVM_EXPAND, Windows does not
1295 * send the selection changed notification. This is not
1296 * strictly wrong but is inconsistent. The fix is to
1297 * check whether the selection has changed and issue
1298 * the event.
1299 */
1300 auto hOldItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
1301
1302 /* Expand or collapse the item */
1303 parent.ignoreExpand = true;
1304 OS.SendMessage (hwnd, OS.TVM_EXPAND, expanded ? OS.TVE_EXPAND : OS.TVE_COLLAPSE, handle);
1305 parent.ignoreExpand = false;
1306
1307 /* Scroll back to the top item */
1308 if (noScroll && hTopItem !is null) {
1309 bool collapsed = false;
1310 if (!expanded) {
1311 RECT rect;
1312 while (hTopItem !is null && !OS.TreeView_GetItemRect (hwnd, cast(HTREEITEM)hTopItem, &rect, false)) {
1313 hTopItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hTopItem);
1314 collapsed = true;
1315 }
1316 }
1317 bool scrolled = true;
1318 if (hTopItem !is null) {
1319 OS.SendMessage (hwnd, OS.TVM_SELECTITEM, OS.TVGN_FIRSTVISIBLE, hTopItem);
1320 scrolled = hTopItem !is cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
1321 }
1322 if (!collapsed && !scrolled && oldInfo !is null ) {
1323 SCROLLINFO newInfo;
1324 newInfo.cbSize = SCROLLINFO.sizeof;
1325 newInfo.fMask = OS.SIF_ALL;
1326 if (OS.GetScrollInfo (hwnd, OS.SB_HORZ, &newInfo)) {
1327 if (oldInfo.nPos !is newInfo.nPos) {
1328 int /*long*/ lParam = OS.MAKELPARAM (OS.SB_THUMBPOSITION, oldInfo.nPos);
1329 OS.SendMessage (hwnd, OS.WM_HSCROLL, lParam, 0);
1330 }
1331 }
1332 }
1333 if (redraw) {
1334 bool fixScroll = false;
1335 if (!collapsed && !scrolled) {
1336 RECT newRect;
1337 OS.GetClientRect (hwnd, &newRect);
1338 if (OS.EqualRect (&oldRect, &newRect)) {
1339 HANDLE hItem = hTopItem;
1340 int index = 0;
1341 while (hItem !is null && index < count) {
1342 RECT rect;
1343 if (OS.TreeView_GetItemRect (hwnd, cast(HTREEITEM)hItem, &rect, true)) {
1344 if (!OS.EqualRect (&rect, & rects [index])) {
1345 break;
1346 }
1347 }
1348 hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
1349 index++;
1350 }
1351 fixScroll = index is count && hItem is hBottomItem;
1352 }
1353 }
1354 auto topHandle = parent.topHandle ();
1355 OS.DefWindowProc (topHandle, OS.WM_SETREDRAW, 1, 0);
1356 if (hwnd !is topHandle) {
1357 OS.DefWindowProc (hwnd, OS.WM_SETREDRAW, 1, 0);
1358 }
1359 /*
1360 * This code is intentionally commented.
1361 */
1362 // OS.SendMessage (hwnd, OS.WM_SETREDRAW, 1, 0);
1363 if (fixScroll) {
1364 parent.updateScrollBar ();
1365 SCROLLINFO info;
1366 info.cbSize = SCROLLINFO.sizeof;
1367 info.fMask = OS.SIF_ALL;
1368 if (OS.GetScrollInfo (hwnd, OS.SB_VERT, &info)) {
1369 OS.SetScrollInfo (hwnd, OS.SB_VERT, &info, true);
1370 }
1371 if (handle is hBottomItem) {
1372 RECT rect;
1373 if (OS.TreeView_GetItemRect (hwnd, cast(HTREEITEM)hBottomItem, &rect, false)) {
1374 OS.InvalidateRect (hwnd, &rect, true);
1375 }
1376 }
1377 } else {
1378 static if (OS.IsWinCE) {
1379 OS.InvalidateRect (topHandle, null, true);
1380 if (hwnd !is topHandle) OS.InvalidateRect (hwnd, null, true);
1381 } else {
1382 int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
1383 OS.RedrawWindow (topHandle, null, null, flags);
1384 }
1385 }
1386 }
1387 }
1388
1389 /* Check for a selection event */
1390 auto hNewItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
1391 if (hNewItem !is hOldItem) {
1392 Event event = new Event ();
1393 if (hNewItem !is null) {
1394 event.item = parent._getItem (hNewItem);
1395 parent.hAnchor = hNewItem;
1396 }
1397 parent.sendEvent (SWT.Selection, event);
1398 }
1399 }
1400
1401 /**
1402 * Sets the font that the receiver will use to paint textual information
1403 * for this item to the font specified by the argument, or to the default font
1404 * for that kind of control if the argument is null.
1405 *
1406 * @param font the new font (or null)
1407 *
1408 * @exception IllegalArgumentException <ul>
1409 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
1410 * </ul>
1411 * @exception SWTException <ul>
1412 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1413 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1414 * </ul>
1415 *
1416 * @since 3.0
1417 */
1418 public void setFont (Font font){
1419 checkWidget ();
1420 if (font !is null && font.isDisposed ()) {
1421 SWT.error (SWT.ERROR_INVALID_ARGUMENT);
1422 }
1423 Font oldFont = this.font;
1424 if (oldFont is font) return;
1425 this.font = font;
1426 if (oldFont !is null && oldFont.opEquals (font)) return;
1427 if (font !is null) parent.customDraw = true;
1428 if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
1429 /*
1430 * Bug in Windows. When the font is changed for an item,
1431 * the bounds for the item are not updated, causing the text
1432 * to be clipped. The fix is to reset the text, causing
1433 * Windows to compute the new bounds using the new font.
1434 */
1435 if ((parent.style & SWT.VIRTUAL) is 0 && !cached && !parent.painted) {
1436 return;
1437 }
1438 auto hwnd = parent.handle;
1439 TVITEM tvItem;
1440 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_TEXT;
1441 tvItem.hItem = cast(HTREEITEM)handle;
1442 tvItem.pszText = OS.LPSTR_TEXTCALLBACK;
1443 OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, &tvItem);
1444 }
1445
1446
1447 /**
1448 * Sets the font that the receiver will use to paint textual information
1449 * for the specified cell in this item to the font specified by the
1450 * argument, or to the default font for that kind of control if the
1451 * argument is null.
1452 *
1453 * @param index the column index
1454 * @param font the new font (or null)
1455 *
1456 * @exception IllegalArgumentException <ul>
1457 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
1458 * </ul>
1459 * @exception SWTException <ul>
1460 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1461 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1462 * </ul>
1463 *
1464 * @since 3.1
1465 */
1466 public void setFont (int index, Font font) {
1467 checkWidget ();
1468 if (font !is null && font.isDisposed ()) {
1469 SWT.error (SWT.ERROR_INVALID_ARGUMENT);
1470 }
1471 int count = Math.max (1, parent.getColumnCount ());
1472 if (0 > index || index > count - 1) return;
1473 if (cellFont is null) {
1474 if (font is null) return;
1475 cellFont = new Font [count];
1476 }
1477 Font oldFont = cellFont [index];
1478 if (oldFont is font) return;
1479 cellFont [index] = font;
1480 if (oldFont !is null && oldFont.opEquals (font)) return;
1481 if (font !is null) parent.customDraw = true;
1482 if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
1483 /*
1484 * Bug in Windows. When the font is changed for an item,
1485 * the bounds for the item are not updated, causing the text
1486 * to be clipped. The fix is to reset the text, causing
1487 * Windows to compute the new bounds using the new font.
1488 */
1489 if (index is 0) {
1490 if ((parent.style & SWT.VIRTUAL) is 0 && !cached && !parent.painted) {
1491 return;
1492 }
1493 auto hwnd = parent.handle;
1494 TVITEM tvItem;
1495 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_TEXT;
1496 tvItem.hItem = cast(HTREEITEM)handle;
1497 tvItem.pszText = OS.LPSTR_TEXTCALLBACK;
1498 OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, &tvItem);
1499 } else {
1500 redraw (index, true, false);
1501 }
1502 }
1503
1504 /**
1505 * Sets the receiver's foreground color to the color specified
1506 * by the argument, or to the default system color for the item
1507 * if the argument is null.
1508 *
1509 * @param color the new color (or null)
1510 *
1511 * @since 2.0
1512 *
1513 * @exception IllegalArgumentException <ul>
1514 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
1515 * </ul>
1516 * @exception SWTException <ul>
1517 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1518 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1519 * </ul>
1520 *
1521 * @since 2.0
1522 *
1523 */
1524 public void setForeground (Color color) {
1525 checkWidget ();
1526 if (color !is null && color.isDisposed ()) {
1527 SWT.error (SWT.ERROR_INVALID_ARGUMENT);
1528 }
1529 int pixel = -1;
1530 if (color !is null) {
1531 parent.customDraw = true;
1532 pixel = color.handle;
1533 }
1534 if (foreground is pixel) return;
1535 foreground = pixel;
1536 if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
1537 redraw ();
1538 }
1539
1540 /**
1541 * Sets the foreground color at the given column index in the receiver
1542 * to the color specified by the argument, or to the default system color for the item
1543 * if the argument is null.
1544 *
1545 * @param index the column index
1546 * @param color the new color (or null)
1547 *
1548 * @exception IllegalArgumentException <ul>
1549 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
1550 * </ul>
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>
1554 * </ul>
1555 *
1556 * @since 3.1
1557 *
1558 */
1559 public void setForeground (int index, Color color){
1560 checkWidget ();
1561 if (color !is null && color.isDisposed ()) {
1562 SWT.error (SWT.ERROR_INVALID_ARGUMENT);
1563 }
1564 int count = Math.max (1, parent.getColumnCount ());
1565 if (0 > index || index > count - 1) return;
1566 int pixel = -1;
1567 if (color !is null) {
1568 parent.customDraw = true;
1569 pixel = color.handle;
1570 }
1571 if (cellForeground is null) {
1572 cellForeground = new int [count];
1573 for (int i = 0; i < count; i++) {
1574 cellForeground [i] = -1;
1575 }
1576 }
1577 if (cellForeground [index] is pixel) return;
1578 cellForeground [index] = pixel;
1579 if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
1580 redraw (index, true, false);
1581 }
1582
1583 /**
1584 * Sets the grayed state of the checkbox for this item. This state change
1585 * only applies if the Tree was created with the SWT.CHECK style.
1586 *
1587 * @param grayed the new grayed state of the checkbox
1588 *
1589 * @exception SWTException <ul>
1590 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1591 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1592 * </ul>
1593 */
1594 public void setGrayed (bool grayed) {
1595 checkWidget ();
1596 if ((parent.style & SWT.CHECK) is 0) return;
1597 auto hwnd = parent.handle;
1598 TVITEM tvItem;
1599 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
1600 tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
1601 tvItem.hItem = cast(HTREEITEM)handle;
1602 OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, &tvItem);
1603 int state = tvItem.state >> 12;
1604 if (grayed) {
1605 if (state <= 2) state +=2;
1606 } else {
1607 if (state > 2) state -=2;
1608 }
1609 state <<= 12;
1610 if (tvItem.state is state) return;
1611 if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
1612 tvItem.state = state;
1613 OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, &tvItem);
1614 /*
1615 * Bug in Windows. When TVM_SETITEM is used to set
1616 * the state image of an item inside TVN_GETDISPINFO,
1617 * the new state is not redrawn. The fix is to force
1618 * a redraw.
1619 */
1620 if ((parent.style & SWT.VIRTUAL) !is 0) {
1621 if (parent.currentItem is this && OS.IsWindowVisible (hwnd)) {
1622 RECT rect;
1623 if (OS.TreeView_GetItemRect (hwnd, cast(HTREEITEM)handle, &rect, false)) {
1624 OS.InvalidateRect (hwnd, &rect, true);
1625 }
1626 }
1627 }
1628 }
1629
1630 /**
1631 * Sets the image for multiple columns in the tree.
1632 *
1633 * @param images the array of new images
1634 *
1635 * @exception IllegalArgumentException <ul>
1636 * <li>ERROR_INVALID_ARGUMENT - if one of the images has been disposed</li>
1637 * </ul>
1638 * @exception SWTException <ul>
1639 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1640 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1641 * </ul>
1642 *
1643 * @since 3.1
1644 */
1645 public void setImage (Image [] images) {
1646 checkWidget();
1647 // SWT extension; allow null array
1648 //if (images is null) error (SWT.ERROR_NULL_ARGUMENT);
1649 for (int i=0; i<images.length; i++) {
1650 setImage (i, images [i]);
1651 }
1652 }
1653
1654 /**
1655 * Sets the receiver's image at a column.
1656 *
1657 * @param index the column index
1658 * @param image the new image
1659 *
1660 * @exception IllegalArgumentException <ul>
1661 * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
1662 * </ul>
1663 * @exception SWTException <ul>
1664 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1665 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1666 * </ul>
1667 *
1668 * @since 3.1
1669 */
1670 public void setImage (int index, Image image) {
1671 checkWidget();
1672 if (image !is null && image.isDisposed ()) {
1673 error(SWT.ERROR_INVALID_ARGUMENT);
1674 }
1675 Image oldImage = null;
1676 if (index is 0) {
1677 if (image !is null && image.type is SWT.ICON) {
1678 if (image==/*eq*/this.image) return;
1679 }
1680 oldImage = this.image;
1681 super.setImage (image);
1682 }
1683 int count = Math.max (1, parent.getColumnCount ());
1684 if (0 > index || index > count - 1) return;
1685 if (images is null && index !is 0) {
1686 images = new Image [count];
1687 images [0] = image;
1688 }
1689 if (images !is null) {
1690 if (image !is null && image.type is SWT.ICON) {
1691 if (image==/*eq*/images [index]) return;
1692 }
1693 oldImage = images [index];
1694 images [index] = image;
1695 }
1696 if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
1697
1698 /* Ensure that the image list is created */
1699 //TODO - items that are not in column zero don't need to be in the image list
1700 parent.imageIndex (image, index);
1701
1702 if (index is 0) {
1703 if ((parent.style & SWT.VIRTUAL) is 0 &&!cached && !parent.painted) {
1704 return;
1705 }
1706 auto hwnd = parent.handle;
1707 TVITEM tvItem;
1708 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_IMAGE | OS.TVIF_SELECTEDIMAGE;
1709 tvItem.hItem = cast(HTREEITEM)handle;
1710 tvItem.iImage = tvItem.iSelectedImage = OS.I_IMAGECALLBACK;
1711 /*
1712 * Bug in Windows. When I_IMAGECALLBACK is used with TVM_SETITEM
1713 * to indicate that an image has changed, Windows does not draw
1714 * the new image. The fix is to use LPSTR_TEXTCALLBACK to force
1715 * Windows to ask for the text, causing Windows to ask for both.
1716 */
1717 tvItem.mask |= OS.TVIF_TEXT;
1718 tvItem.pszText = OS.LPSTR_TEXTCALLBACK;
1719 OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, &tvItem);
1720 } else {
1721 bool drawText = (image is null && oldImage !is null) || (image !is null && oldImage is null);
1722 redraw (index, drawText, true);
1723 }
1724 }
1725
1726 override public void setImage (Image image) {
1727 checkWidget ();
1728 setImage (0, image);
1729 }
1730
1731 /**
1732 * Sets the number of child items contained in the receiver.
1733 *
1734 * @param count the number of items
1735 *
1736 * @exception SWTException <ul>
1737 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1738 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1739 * </ul>
1740 *
1741 * @since 3.2
1742 */
1743 public void setItemCount (int count) {
1744 checkWidget ();
1745 count = Math.max (0, count);
1746 auto hwnd = parent.handle;
1747 auto hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
1748 parent.setItemCount (count, handle, hItem);
1749 }
1750
1751 /**
1752 * Sets the text for multiple columns in the tree.
1753 *
1754 * @param strings the array of new strings
1755 *
1756 * @exception SWTException <ul>
1757 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1758 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1759 * </ul>
1760 *
1761 * @since 3.1
1762 */
1763 public void setText (String[] strings) {
1764 checkWidget();
1765 // SWT extension: allow null array
1766 //if (strings is null) error (SWT.ERROR_NULL_ARGUMENT);
1767 for (int i=0; i<strings.length; i++) {
1768 String string = strings [i];
1769 if (string !is null) setText (i, string);
1770 }
1771 }
1772
1773 /**
1774 * Sets the receiver's text at a column
1775 *
1776 * @param index the column index
1777 * @param string the new text
1778 *
1779 * @exception SWTException <ul>
1780 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1781 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1782 * </ul>
1783 *
1784 * @since 3.1
1785 */
1786 public void setText (int index, String string) {
1787 checkWidget();
1788 // SWT extension: allow null string
1789 //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
1790 if (index is 0) {
1791 if (string==/*eq*/text) return;
1792 super.setText (string);
1793 }
1794 int count = Math.max (1, parent.getColumnCount ());
1795 if (0 > index || index > count - 1) return;
1796 if (strings is null && index !is 0) {
1797 strings = new String [count];
1798 strings [0] = text;
1799 }
1800 if (strings !is null) {
1801 if (string==/*eq*/strings [index]) return;
1802 strings [index] = string;
1803 }
1804 if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
1805 if (index is 0) {
1806 if ((parent.style & SWT.VIRTUAL) is 0 && !cached && !parent.painted) {
1807 return;
1808 }
1809 auto hwnd = parent.handle;
1810 TVITEM tvItem;
1811 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_TEXT;
1812 tvItem.hItem = cast(HTREEITEM)handle;
1813 tvItem.pszText = OS.LPSTR_TEXTCALLBACK;
1814 OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, &tvItem);
1815 } else {
1816 redraw (index, true, false);
1817 }
1818 }
1819
1820 override public void setText (String string) {
1821 checkWidget();
1822 setText (0, string);
1823 }
1824
1825 /*public*/ void sort () {
1826 checkWidget ();
1827 if ((parent.style & SWT.VIRTUAL) !is 0) return;
1828 parent.sort (handle, false);
1829 }
1830
1831 }
1832