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 java.lang.all;
16 
17 
18 
19 import org.eclipse.swt.SWT;
20 import org.eclipse.swt.SWTException;
21 import org.eclipse.swt.graphics.Color;
22 import org.eclipse.swt.graphics.Font;
23 import org.eclipse.swt.graphics.Image;
24 import org.eclipse.swt.graphics.Rectangle;
25 import org.eclipse.swt.internal.gtk.OS;
26 import org.eclipse.swt.widgets.Item;
27 import org.eclipse.swt.widgets.Tree;
28 import org.eclipse.swt.widgets.ImageList;
29 
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 public class TreeItem : Item {
49     Tree parent;
50     Font font;
51     Font[] cellFont;
52     bool cached, grayed;
53     static const int EXPANDER_EXTRA_PADDING = 4;
54 
55 /**
56  * Constructs a new instance of this class given its parent
57  * (which must be a <code>Tree</code> or a <code>TreeItem</code>)
58  * and a style value describing its behavior and appearance.
59  * The item is added to the end of the items maintained by its parent.
60  * <p>
61  * The style value is either one of the style constants defined in
62  * class <code>SWT</code> which is applicable to instances of this
63  * class, or must be built by <em>bitwise OR</em>'ing together
64  * (that is, using the <code>int</code> "|" operator) two or more
65  * of those <code>SWT</code> style constants. The class description
66  * lists the style constants that are applicable to the class.
67  * Style bits are also inherited from superclasses.
68  * </p>
69  *
70  * @param parent a tree control which will be the parent of the new instance (cannot be null)
71  * @param style the style of control to construct
72  *
73  * @exception IllegalArgumentException <ul>
74  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
75  * </ul>
76  * @exception SWTException <ul>
77  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
78  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
79  * </ul>
80  *
81  * @see SWT
82  * @see Widget#checkSubclass
83  * @see Widget#getStyle
84  */
85 public this (Tree parent, int style) {
86     this (checkNull (parent), null, style, -1, true);
87 }
88 
89 /**
90  * Constructs a new instance of this class given its parent
91  * (which must be a <code>Tree</code> or a <code>TreeItem</code>),
92  * a style value describing its behavior and appearance, and the index
93  * at which to place it in the items maintained by its parent.
94  * <p>
95  * The style value is either one of the style constants defined in
96  * class <code>SWT</code> which is applicable to instances of this
97  * class, or must be built by <em>bitwise OR</em>'ing together
98  * (that is, using the <code>int</code> "|" operator) two or more
99  * of those <code>SWT</code> style constants. The class description
100  * lists the style constants that are applicable to the class.
101  * Style bits are also inherited from superclasses.
102  * </p>
103  *
104  * @param parent a tree control which will be the parent of the new instance (cannot be null)
105  * @param style the style of control to construct
106  * @param index the zero-relative index to store the receiver in its parent
107  *
108  * @exception IllegalArgumentException <ul>
109  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
110  *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
111  * </ul>
112  * @exception SWTException <ul>
113  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
114  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
115  * </ul>
116  *
117  * @see SWT
118  * @see Widget#checkSubclass
119  * @see Widget#getStyle
120  */
121 public this (Tree parent, int style, int index) {
122     this (checkNull (parent), null, style, checkIndex (index), true);
123 }
124 
125 /**
126  * Constructs a new instance of this class given its parent
127  * (which must be a <code>Tree</code> or a <code>TreeItem</code>)
128  * and a style value describing its behavior and appearance.
129  * The item is added to the end of the items maintained by its parent.
130  * <p>
131  * The style value is either one of the style constants defined in
132  * class <code>SWT</code> which is applicable to instances of this
133  * class, or must be built by <em>bitwise OR</em>'ing together
134  * (that is, using the <code>int</code> "|" operator) two or more
135  * of those <code>SWT</code> style constants. The class description
136  * lists the style constants that are applicable to the class.
137  * Style bits are also inherited from superclasses.
138  * </p>
139  *
140  * @param parentItem a tree control which will be the parent of the new instance (cannot be null)
141  * @param style the style of control to construct
142  *
143  * @exception IllegalArgumentException <ul>
144  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
145  * </ul>
146  * @exception SWTException <ul>
147  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
148  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
149  * </ul>
150  *
151  * @see SWT
152  * @see Widget#checkSubclass
153  * @see Widget#getStyle
154  */
155 public this (TreeItem parentItem, int style) {
156     this (checkNull (parentItem).parent, cast(GtkTreeIter*)parentItem.handle, style, -1, true);
157 }
158 
159 /**
160  * Constructs a new instance of this class given its parent
161  * (which must be a <code>Tree</code> or a <code>TreeItem</code>),
162  * a style value describing its behavior and appearance, and the index
163  * at which to place it in the items maintained by its parent.
164  * <p>
165  * The style value is either one of the style constants defined in
166  * class <code>SWT</code> which is applicable to instances of this
167  * class, or must be built by <em>bitwise OR</em>'ing together
168  * (that is, using the <code>int</code> "|" operator) two or more
169  * of those <code>SWT</code> style constants. The class description
170  * lists the style constants that are applicable to the class.
171  * Style bits are also inherited from superclasses.
172  * </p>
173  *
174  * @param parentItem a tree control which will be the parent of the new instance (cannot be null)
175  * @param style the style of control to construct
176  * @param index the zero-relative index to store the receiver in its parent
177  *
178  * @exception IllegalArgumentException <ul>
179  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
180  *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
181  * </ul>
182  * @exception SWTException <ul>
183  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
184  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
185  * </ul>
186  *
187  * @see SWT
188  * @see Widget#checkSubclass
189  * @see Widget#getStyle
190  */
191 public this (TreeItem parentItem, int style, int index) {
192     this (checkNull (parentItem).parent, cast(GtkTreeIter*)parentItem.handle, style, checkIndex (index), true);
193 }
194 
195 this (Tree parent, GtkTreeIter* parentIter, int style, int index, bool create) {
196     super (parent, style);
197     this.parent = parent;
198     if (create) {
199         parent.createItem (this, parentIter, index);
200     } else {
201         handle = cast(GtkWidget*)OS.g_malloc (GtkTreeIter.sizeof);
202         OS.gtk_tree_model_iter_nth_child (parent.modelHandle, handle, parentIter, index);
203     }
204 }
205 
206 static int checkIndex (int index) {
207     if (index < 0) SWT.error (SWT.ERROR_INVALID_RANGE);
208     return index;
209 }
210 
211 static TreeItem checkNull (TreeItem item) {
212     if (item is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
213     return item;
214 }
215 
216 static Tree checkNull (Tree control) {
217     if (control is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
218     return control;
219 }
220 
221 protected override void checkSubclass () {
222     if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
223 }
224 
225 Color _getBackground () {
226     void* ptr;
227     OS.gtk_tree_model_get1 (parent.modelHandle, handle, Tree.BACKGROUND_COLUMN, &ptr);
228     if (ptr is null) return parent.getBackground ();
229     GdkColor* gdkColor = new GdkColor ();
230     *gdkColor = *cast(GdkColor*) ptr;
231     return Color.gtk_new (display, gdkColor);
232 }
233 
234 Color _getBackground (int index) {
235     int count = Math.max (1, parent.columnCount);
236     if (0 > index || index > count - 1) return _getBackground ();
237     void* ptr;
238     int modelIndex = parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex;
239     OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Tree.CELL_BACKGROUND, &ptr);
240     if (ptr is null) return _getBackground ();
241     GdkColor* gdkColor = new GdkColor ();
242     *gdkColor = *cast(GdkColor*) ptr;
243     return Color.gtk_new (display, gdkColor);
244 }
245 
246 bool _getChecked () {
247     void* ptr;
248     OS.gtk_tree_model_get1 (parent.modelHandle, handle, Tree.CHECKED_COLUMN, &ptr);
249     return ptr !is null;
250 }
251 
252 Color _getForeground () {
253     void* ptr;
254     OS.gtk_tree_model_get1 (parent.modelHandle, handle, Tree.FOREGROUND_COLUMN, &ptr);
255     if (ptr is null) return parent.getForeground ();
256     GdkColor* gdkColor = new GdkColor ();
257     *gdkColor = *cast(GdkColor*) ptr;
258     return Color.gtk_new (display, gdkColor);
259 }
260 
261 Color _getForeground (int index) {
262     int count = Math.max (1, parent.columnCount);
263     if (0 > index || index > count - 1) return _getForeground ();
264     void* ptr;
265     int modelIndex =  parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex;
266     OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Tree.CELL_FOREGROUND, &ptr);
267     if (ptr is null) return _getForeground ();
268     GdkColor* gdkColor = new GdkColor ();
269     *gdkColor = *cast(GdkColor*) ptr;
270     return Color.gtk_new (display, gdkColor);
271 }
272 
273 Image _getImage (int index) {
274     int count = Math.max (1, parent.getColumnCount ());
275     if (0 > index || index > count - 1) return null;
276     void* ptr;
277     int modelIndex = parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex;
278     OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Tree.CELL_PIXBUF, &ptr);
279     if (ptr is null) return null;
280     ImageList imageList = parent.imageList;
281     int imageIndex = imageList.indexOf (ptr);
282     if (imageIndex is -1) return null;
283     return imageList.get (imageIndex);
284 }
285 
286 String _getText (int index) {
287     int count = Math.max (1, parent.getColumnCount ());
288     if (0 > index || index > count - 1) return "";
289     void* ptr;
290     int modelIndex = parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex;
291     OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Tree.CELL_TEXT, &ptr);
292     if (ptr is null) return ""; //$NON-NLS-1$
293     String buffer = fromStringz( cast(char*)ptr)._idup();
294     OS.g_free (ptr);
295     return buffer;
296 }
297 
298 void clear () {
299     if (parent.currentItem is this) return;
300     if (cached || (parent.style & SWT.VIRTUAL) is 0) {
301         int columnCount = OS.gtk_tree_model_get_n_columns (parent.modelHandle);
302         for (int i=Tree.CHECKED_COLUMN; i<columnCount; i++) {
303             OS.gtk_tree_store_set1(parent.modelHandle, cast(GtkTreeIter*)handle, i, null);
304         }
305         /*
306         * Bug in GTK.  When using fixed-height-mode,
307         * row changes do not cause the row to be repainted.  The fix is to
308         * invalidate the row when it is cleared.
309         */
310         if ((parent.style & SWT.VIRTUAL) !is 0) {
311             if (OS.GTK_VERSION >= OS.buildVERSION (2, 3, 2) && OS.GTK_VERSION < OS.buildVERSION (2, 6, 3)) {
312                 redraw ();
313             }
314         }
315     }
316     cached = false;
317     font = null;
318     cellFont = null;
319 }
320 
321 /**
322  * Clears the item at the given zero-relative index in the receiver.
323  * The text, icon and other attributes of the item are set to the default
324  * value.  If the tree was created with the <code>SWT.VIRTUAL</code> style,
325  * these attributes are requested again as needed.
326  *
327  * @param index the index of the item to clear
328  * @param all <code>true</code> if all child items of the indexed item should be
329  * cleared recursively, and <code>false</code> otherwise
330  *
331  * @exception IllegalArgumentException <ul>
332  *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
333  * </ul>
334  * @exception SWTException <ul>
335  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
336  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
337  * </ul>
338  *
339  * @see SWT#VIRTUAL
340  * @see SWT#SetData
341  *
342  * @since 3.2
343  */
344 public void clear (int index, bool all) {
345     checkWidget ();
346     parent.clear (cast(GtkTreeIter*)handle, index, all);
347 }
348 
349 /**
350  * Clears all the items in the receiver. The text, icon and other
351  * attributes of the items are set to their default values. If the
352  * tree was created with the <code>SWT.VIRTUAL</code> style, these
353  * attributes are requested again as needed.
354  *
355  * @param all <code>true</code> if all child items should be cleared
356  * recursively, and <code>false</code> otherwise
357  *
358  * @exception SWTException <ul>
359  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
360  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
361  * </ul>
362  *
363  * @see SWT#VIRTUAL
364  * @see SWT#SetData
365  *
366  * @since 3.2
367  */
368 public void clearAll (bool all) {
369     checkWidget ();
370     parent.clearAll (all, cast(GtkTreeIter*)handle);
371 }
372 
373 override void destroyWidget () {
374     parent.releaseItem (this, false);
375     parent.destroyItem (this);
376     releaseHandle ();
377 }
378 
379 /**
380  * Returns the receiver's background color.
381  *
382  * @return the background color
383  *
384  * @exception SWTException <ul>
385  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
386  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
387  * </ul>
388  *
389  * @since 2.0
390  *
391  */
392 public Color getBackground () {
393     checkWidget ();
394     if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
395     return _getBackground ();
396 }
397 
398 /**
399  * Returns the background color at the given column index in the receiver.
400  *
401  * @param index the column index
402  * @return the background color
403  *
404  * @exception SWTException <ul>
405  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
406  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
407  * </ul>
408  *
409  * @since 3.1
410  */
411 public Color getBackground (int index) {
412     checkWidget ();
413     if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
414     return _getBackground (index);
415 }
416 
417 /**
418  * Returns a rectangle describing the receiver's size and location
419  * relative to its parent at a column in the tree.
420  *
421  * @param index the index that specifies the column
422  * @return the receiver's bounding column rectangle
423  *
424  * @exception SWTException <ul>
425  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
426  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
427  * </ul>
428  *
429  * @since 3.1
430  */
431 public Rectangle getBounds (int index) {
432     // TODO fully test on early and later versions of GTK
433     checkWidget();
434     if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
435     auto parentHandle = parent.handle;
436     GtkTreeViewColumn* column;
437     if (index >= 0 && index < parent.columnCount) {
438         column = cast(GtkTreeViewColumn*)parent.columns [index].handle;
439     } else {
440         column = OS.gtk_tree_view_get_column (parentHandle, index);
441     }
442     if (column is null) return new Rectangle (0, 0, 0, 0);
443     auto path = OS.gtk_tree_model_get_path (parent.modelHandle, handle);
444     OS.gtk_widget_realize (parentHandle);
445     GdkRectangle rect;
446     OS.gtk_tree_view_get_cell_area (parentHandle, path, column, &rect);
447     if ((parent.getStyle () & SWT.MIRRORED) !is 0) rect.x = parent.getClientWidth () - rect.width - rect.x;
448 
449     if (OS.GTK_VERSION < OS.buildVERSION (2, 8, 18) && OS.gtk_tree_view_get_expander_column (parentHandle) is column) {
450         int buffer;
451         OS.gtk_widget_style_get1 (parentHandle, OS.expander_size.ptr, &buffer);
452         rect.x += buffer + TreeItem.EXPANDER_EXTRA_PADDING;
453         rect.width -= buffer + TreeItem.EXPANDER_EXTRA_PADDING;
454         OS.gtk_widget_style_get1 (parentHandle, OS.horizontal_separator.ptr, &buffer);
455         rect.x += buffer;
456         //rect.width -= buffer [0]; // TODO Is this required for some versions?
457     }
458     /*
459     * Bug in GTK. In GTK 2.8.x, the cell area is left aligned even
460     * when the widget is mirrored. The fix is to sum up the indentation
461     * of the expanders.
462     */
463     if ((parent.getStyle () & SWT.MIRRORED) !is 0 && (OS.GTK_VERSION < OS.buildVERSION (2, 10, 0))) {
464         int depth = OS.gtk_tree_path_get_depth (path);
465         int  expanderSize;
466         OS.gtk_widget_style_get1 (parentHandle, OS.expander_size.ptr, &expanderSize);
467         rect.x += depth * (expanderSize + TreeItem.EXPANDER_EXTRA_PADDING);
468     }
469     OS.gtk_tree_path_free (path);
470 
471     if (index is 0 && (parent.style & SWT.CHECK) !is 0) {
472         if (OS.GTK_VERSION >= OS.buildVERSION (2, 1, 3)) {
473             int  x, w;
474             OS.gtk_tree_view_column_cell_get_position (column, parent.checkRenderer, &x, &w);
475             rect.x += x + w;
476             rect.width -= x + w;
477         } else {
478             int w;
479             OS.gtk_cell_renderer_get_size (parent.checkRenderer, parentHandle, null, null, null, &w, null);
480             int buffer;
481             OS.gtk_widget_style_get1 (parentHandle, OS.horizontal_separator.ptr, &buffer);
482             rect.x += w  + buffer;
483             rect.width -= w  + buffer;
484         }
485     }
486     int width = OS.gtk_tree_view_column_get_visible (column) ? rect.width + 1 : 0;
487     return new Rectangle (rect.x, rect.y, width, rect.height + 1);
488 }
489 
490 /**
491  * Returns a rectangle describing the receiver's size and location
492  * relative to its parent.
493  *
494  * @return the receiver's bounding rectangle
495  *
496  * @exception SWTException <ul>
497  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
498  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
499  * </ul>
500  */
501 public Rectangle getBounds () {
502     // TODO fully test on early and later versions of GTK
503     // shifted a bit too far right on later versions of GTK - however, old Tree also had this problem
504     checkWidget ();
505     if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
506     auto parentHandle = parent.handle;
507     auto column = OS.gtk_tree_view_get_column (parentHandle, 0);
508     if (column is null) return new Rectangle (0, 0, 0, 0);
509     auto textRenderer = parent.getTextRenderer (column);
510     auto pixbufRenderer = parent.getPixbufRenderer (column);
511     if (textRenderer is null || pixbufRenderer is null)  return new Rectangle (0, 0, 0, 0);
512 
513     auto path = OS.gtk_tree_model_get_path (parent.modelHandle, handle);
514     OS.gtk_widget_realize (parentHandle);
515 
516     bool isExpander = OS.gtk_tree_model_iter_n_children (parent.modelHandle, handle) > 0;
517     bool isExpanded = cast(bool)OS.gtk_tree_view_row_expanded (parentHandle, path);
518     OS.gtk_tree_view_column_cell_set_cell_data (column, parent.modelHandle, handle, isExpander, isExpanded);
519 
520     GdkRectangle rect;
521     OS.gtk_tree_view_get_cell_area (parentHandle, path, column, &rect);
522     if ((parent.getStyle () & SWT.MIRRORED) !is 0) rect.x = parent.getClientWidth () - rect.width - rect.x;
523     int right = rect.x + rect.width;
524 
525     int x, w;
526     parent.ignoreSize = true;
527     OS.gtk_cell_renderer_get_size (textRenderer, parentHandle, null, null, null, &w, null);
528     parent.ignoreSize = false;
529     rect.width = w;
530     int buffer;
531     if (OS.GTK_VERSION < OS.buildVERSION (2, 8, 18) && OS.gtk_tree_view_get_expander_column (parentHandle) is column) {
532         OS.gtk_widget_style_get1 (parentHandle, OS.expander_size.ptr, &buffer);
533         rect.x += buffer + TreeItem.EXPANDER_EXTRA_PADDING;
534     }
535     /*
536     * Bug in GTK. In GTK 2.8.x, the cell area is left aligned even
537     * when the widget is mirrored. The fix is to sum up the indentation
538     * of the expanders.
539     */
540     if ((parent.getStyle () & SWT.MIRRORED) !is 0 && (OS.GTK_VERSION < OS.buildVERSION (2, 10, 0))) {
541         int depth = OS.gtk_tree_path_get_depth (path);
542         int expanderSize;
543         OS.gtk_widget_style_get1 (parentHandle, OS.expander_size.ptr, &expanderSize);
544         rect.x += depth * (expanderSize + TreeItem.EXPANDER_EXTRA_PADDING);
545     }
546     OS.gtk_tree_path_free (path);
547 
548     OS.gtk_widget_style_get1 (parentHandle, OS.horizontal_separator.ptr, &buffer);
549     int horizontalSeparator = buffer;
550     rect.x += horizontalSeparator;
551 
552     if (OS.GTK_VERSION >= OS.buildVERSION (2, 1, 3)) {
553         OS.gtk_tree_view_column_cell_get_position (column, textRenderer, &x, null);
554         rect.x += x;
555     } else {
556         if ((parent.style & SWT.CHECK) !is 0) {
557             OS.gtk_cell_renderer_get_size (parent.checkRenderer, parentHandle, null, null, null, &w, null);
558             rect.x += w + horizontalSeparator;
559         }
560         OS.gtk_cell_renderer_get_size (pixbufRenderer, parentHandle, null, null, null, &w, null);
561         rect.x += w + horizontalSeparator;
562     }
563     if (parent.columnCount > 0) {
564         if (rect.x + rect.width > right) {
565             rect.width = Math.max (0, right - rect.x);
566         }
567     }
568     int width = OS.gtk_tree_view_column_get_visible (column) ? rect.width + 1 : 0;
569     return new Rectangle (rect.x, rect.y, width, rect.height + 1);
570 }
571 
572 /**
573  * Returns <code>true</code> if the receiver is checked,
574  * and false otherwise.  When the parent does not have
575  * the <code>CHECK style, return false.
576  * <p>
577  *
578  * @return the checked state
579  *
580  * @exception SWTException <ul>
581  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
582  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
583  * </ul>
584  */
585 public bool getChecked () {
586     checkWidget();
587     if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
588     if ((parent.style & SWT.CHECK) is 0) return false;
589     return _getChecked ();
590 }
591 
592 /**
593  * Returns <code>true</code> if the receiver is expanded,
594  * and false otherwise.
595  * <p>
596  *
597  * @return the expanded state
598  *
599  * @exception SWTException <ul>
600  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
601  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
602  * </ul>
603  */
604 public bool getExpanded () {
605     checkWidget();
606     auto path = OS.gtk_tree_model_get_path (parent.modelHandle, handle);
607     bool answer = cast(bool)OS.gtk_tree_view_row_expanded (parent.handle, path);
608     OS.gtk_tree_path_free (path);
609     return answer;
610 }
611 
612 /**
613  * Returns the font that the receiver will use to paint textual information for this item.
614  *
615  * @return the receiver's font
616  *
617  * @exception SWTException <ul>
618  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
619  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
620  * </ul>
621  *
622  * @since 3.0
623  */
624 public Font getFont () {
625     checkWidget ();
626     if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
627     return font !is null ? font : parent.getFont ();
628 }
629 
630 /**
631  * Returns the font that the receiver will use to paint textual information
632  * for the specified cell in this item.
633  *
634  * @param index the column index
635  * @return the receiver's font
636  *
637  * @exception SWTException <ul>
638  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
639  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
640  * </ul>
641  *
642  * @since 3.1
643  */
644 public Font getFont (int index) {
645     checkWidget ();
646     if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
647     int count = Math.max (1, parent.columnCount);
648     if (0 > index || index > count - 1) return getFont ();
649     if (cellFont is null || cellFont [index] is null) return getFont ();
650     return cellFont [index];
651 }
652 
653 
654 /**
655  * Returns the foreground color that the receiver will use to draw.
656  *
657  * @return the receiver's foreground color
658  *
659  * @exception SWTException <ul>
660  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
661  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
662  * </ul>
663  *
664  * @since 2.0
665  *
666  */
667 public Color getForeground () {
668     checkWidget ();
669     if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
670     return _getForeground ();
671 }
672 
673 /**
674  *
675  * Returns the foreground color at the given column index in the receiver.
676  *
677  * @param index the column index
678  * @return the foreground color
679  *
680  * @exception SWTException <ul>
681  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
682  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
683  * </ul>
684  *
685  * @since 3.1
686  */
687 public Color getForeground (int index) {
688     checkWidget ();
689     if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
690     return _getForeground (index);
691 }
692 
693 /**
694  * Returns <code>true</code> if the receiver is grayed,
695  * and false otherwise. When the parent does not have
696  * the <code>CHECK style, return false.
697  * <p>
698  *
699  * @return the grayed state of the checkbox
700  *
701  * @exception SWTException <ul>
702  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
703  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
704  * </ul>
705  */
706 public bool getGrayed () {
707     checkWidget ();
708     if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
709     if ((parent.style & SWT.CHECK) is 0) return false;
710     return grayed;
711 }
712 
713 public override Image getImage () {
714     checkWidget ();
715     if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
716     return getImage (0);
717 }
718 
719 /**
720  * Returns the image stored at the given column index in the receiver,
721  * or null if the image has not been set or if the column does not exist.
722  *
723  * @param index the column index
724  * @return the image stored at the given column index in the receiver
725  *
726  * @exception SWTException <ul>
727  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
728  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
729  * </ul>
730  *
731  * @since 3.1
732  */
733 public Image getImage (int index) {
734     checkWidget ();
735     if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
736     return _getImage (index);
737 }
738 
739 /**
740  * Returns a rectangle describing the size and location
741  * relative to its parent of an image at a column in the
742  * tree.
743  *
744  * @param index the index that specifies the column
745  * @return the receiver's bounding image rectangle
746  *
747  * @exception SWTException <ul>
748  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
749  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
750  * </ul>
751  *
752  * @since 3.1
753  */
754 public Rectangle getImageBounds (int index) {
755     // TODO fully test on early and later versions of GTK
756     checkWidget ();
757     if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
758     auto parentHandle = parent.handle;
759     GtkTreeViewColumn* column;
760     if (index >= 0 && index < parent.getColumnCount ()) {
761         column = cast(GtkTreeViewColumn*)parent.columns [index].handle;
762     } else {
763         column = OS.gtk_tree_view_get_column (parentHandle, index);
764     }
765     if (column is null) return new Rectangle (0, 0, 0, 0);
766     auto pixbufRenderer = parent.getPixbufRenderer (column);
767     if (pixbufRenderer is null)  return new Rectangle (0, 0, 0, 0);
768     GdkRectangle rect;
769     auto path = OS.gtk_tree_model_get_path (parent.modelHandle, handle);
770     OS.gtk_widget_realize (parentHandle);
771     OS.gtk_tree_view_get_cell_area (parentHandle, path, column, &rect);
772     if ((parent.getStyle () & SWT.MIRRORED) !is 0) rect.x = parent.getClientWidth () - rect.width - rect.x;
773     if (OS.GTK_VERSION < OS.buildVERSION (2, 8, 18) && OS.gtk_tree_view_get_expander_column (parentHandle) is column) {
774         int buffer;
775         OS.gtk_widget_style_get1 (parentHandle, OS.expander_size.ptr, &buffer);
776         rect.x += buffer + TreeItem.EXPANDER_EXTRA_PADDING;
777         rect.width -= buffer + TreeItem.EXPANDER_EXTRA_PADDING;
778         //OS.gtk_widget_style_get (parentHandle, OS.horizontal_separator, buffer, 0);
779         //int horizontalSeparator = buffer[0];
780         //rect.x += horizontalSeparator;
781     }
782     /*
783     * Bug in GTK. In GTK 2.8.x, the cell area is left aligned even
784     * when the widget is mirrored. The fix is to sum up the indentation
785     * of the expanders.
786     */
787     if ((parent.getStyle () & SWT.MIRRORED) !is 0 && (OS.GTK_VERSION < OS.buildVERSION (2, 10, 0))) {
788         int depth = OS.gtk_tree_path_get_depth (path);
789         int expanderSize;
790         OS.gtk_widget_style_get1 (parentHandle, OS.expander_size.ptr, &expanderSize);
791         rect.x += depth * (expanderSize + TreeItem.EXPANDER_EXTRA_PADDING);
792     }
793     OS.gtk_tree_path_free (path);
794 
795     /*
796     * The OS call gtk_cell_renderer_get_size() provides the width of image to be drawn
797     * by the cell renderer.  If there is no image in the cell, the width is zero.  If the table contains
798     * images of varying widths, gtk_cell_renderer_get_size() will return the width of the image,
799     * not the width of the area in which the image is drawn.
800     * New API was added in GTK 2.1.3 for determining the full width of the renderer area.
801     * For earlier versions of GTK, the result is only correct if all rows have images of the same
802     * width.
803     */
804     if (OS.GTK_VERSION >= OS.buildVERSION (2, 1, 3)) {
805         int x, w;
806         OS.gtk_tree_view_column_cell_get_position (column, pixbufRenderer, &x, &w);
807         rect.x += x;
808         rect.width = w;
809     } else {
810         int w;
811         OS.gtk_tree_view_column_cell_set_cell_data (column, parent.modelHandle, handle, false, false);
812         OS.gtk_cell_renderer_get_size (pixbufRenderer, parentHandle, null, null, null, &w, null);
813         rect.width = w;
814     }
815     int width = OS.gtk_tree_view_column_get_visible (column) ? rect.width : 0;
816     return new Rectangle (rect.x, rect.y, width, rect.height + 1);
817 }
818 
819 /**
820  * Returns the number of items contained in the receiver
821  * that are direct item children of the receiver.
822  *
823  * @return the number of items
824  *
825  * @exception SWTException <ul>
826  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
827  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
828  * </ul>
829  */
830 public int getItemCount () {
831     checkWidget();
832     if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
833     return OS.gtk_tree_model_iter_n_children (parent.modelHandle, handle);
834 }
835 
836 /**
837  * Returns the item at the given, zero-relative index in the
838  * receiver. Throws an exception if the index is out of range.
839  *
840  * @param index the index of the item to return
841  * @return the item at the given index
842  *
843  * @exception IllegalArgumentException <ul>
844  *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
845  * </ul>
846  * @exception SWTException <ul>
847  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
848  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
849  * </ul>
850  *
851  * @since 3.1
852  */
853 public TreeItem getItem (int index) {
854     checkWidget();
855     if (index < 0) error (SWT.ERROR_INVALID_RANGE);
856     if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
857     int itemCount = OS.gtk_tree_model_iter_n_children (parent.modelHandle, handle);
858     if (index >= itemCount)  error (SWT.ERROR_INVALID_RANGE);
859     return  parent._getItem (cast(GtkTreeIter*)handle, index);
860 }
861 
862 /**
863  * Returns a (possibly empty) array of <code>TreeItem</code>s which
864  * are the direct item children of the receiver.
865  * <p>
866  * Note: This is not the actual structure used by the receiver
867  * to maintain its list of items, so modifying the array will
868  * not affect the receiver.
869  * </p>
870  *
871  * @return the receiver's items
872  *
873  * @exception SWTException <ul>
874  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
875  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
876  * </ul>
877  */
878 public TreeItem [] getItems () {
879     checkWidget();
880     if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
881     return parent.getItems (cast(GtkTreeIter*)handle);
882 }
883 
884 override String getNameText () {
885     if ((parent.style & SWT.VIRTUAL) !is 0) {
886         if (!cached) return "*virtual*"; //$NON-NLS-1$
887     }
888     return super.getNameText ();
889 }
890 
891 /**
892  * Returns the receiver's parent, which must be a <code>Tree</code>.
893  *
894  * @return the receiver's parent
895  *
896  * @exception SWTException <ul>
897  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
898  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
899  * </ul>
900  */
901 public Tree getParent () {
902     checkWidget ();
903     return parent;
904 }
905 
906 /**
907  * Returns the receiver's parent item, which must be a
908  * <code>TreeItem</code> or null when the receiver is a
909  * root.
910  *
911  * @return the receiver's parent item
912  *
913  * @exception SWTException <ul>
914  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
915  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
916  * </ul>
917  */
918 public TreeItem getParentItem () {
919     checkWidget();
920     auto path = OS.gtk_tree_model_get_path (parent.modelHandle, handle);
921     TreeItem item = null;
922     int depth = OS.gtk_tree_path_get_depth (path);
923     if (depth > 1) {
924         OS.gtk_tree_path_up (path);
925         GtkTreeIter iter;
926         if (OS.gtk_tree_model_get_iter (parent.modelHandle, &iter, path)) {
927             item = parent._getItem (&iter);
928         }
929     }
930     OS.gtk_tree_path_free (path);
931     return item;
932 }
933 
934 public override String getText () {
935     checkWidget ();
936     if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
937     return getText (0);
938 }
939 
940 /**
941  * Returns the text stored at the given column index in the receiver,
942  * or empty string if the text has not been set.
943  *
944  * @param index the column index
945  * @return the text stored at the given column index in the receiver
946  *
947  * @exception SWTException <ul>
948  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
949  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
950  * </ul>
951  *
952  * @since 3.1
953  */
954 public String getText (int index) {
955     checkWidget ();
956     if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
957     return _getText (index);
958 }
959 
960 /**
961  * Returns a rectangle describing the size and location
962  * relative to its parent of the text at a column in the
963  * tree.
964  *
965  * @param index the index that specifies the column
966  * @return the receiver's bounding text rectangle
967  *
968  * @exception SWTException <ul>
969  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
970  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
971  * </ul>
972  *
973  * @since 3.3
974  */
975 public Rectangle getTextBounds (int index) {
976     checkWidget ();
977     if (!parent.checkData (this)) error (SWT.ERROR_WIDGET_DISPOSED);
978     int count = Math.max (1, parent.getColumnCount ());
979     if (0 > index || index > count - 1) return new Rectangle (0, 0, 0, 0);
980     // TODO fully test on early and later versions of GTK
981     // shifted a bit too far right on later versions of GTK - however, old Tree also had this problem
982     auto parentHandle = parent.handle;
983     GtkTreeViewColumn* column;
984     if (index >= 0 && index < parent.columnCount) {
985         column = cast(GtkTreeViewColumn*)parent.columns [index].handle;
986     } else {
987         column = OS.gtk_tree_view_get_column (parentHandle, index);
988     }
989     if (column is null) return new Rectangle (0, 0, 0, 0);
990     auto textRenderer = parent.getTextRenderer (column);
991     auto pixbufRenderer = parent.getPixbufRenderer (column);
992     if (textRenderer is null || pixbufRenderer is null)  return new Rectangle (0, 0, 0, 0);
993 
994     auto path = OS.gtk_tree_model_get_path (parent.modelHandle, handle);
995     OS.gtk_widget_realize (parentHandle);
996 
997     bool isExpander = OS.gtk_tree_model_iter_n_children (parent.modelHandle, handle) > 0;
998     bool isExpanded = cast(bool)OS.gtk_tree_view_row_expanded (parentHandle, path);
999     OS.gtk_tree_view_column_cell_set_cell_data (column, parent.modelHandle, handle, isExpander, isExpanded);
1000 
1001     GdkRectangle rect;
1002     OS.gtk_tree_view_get_cell_area (parentHandle, path, column, &rect);
1003     if ((parent.getStyle () & SWT.MIRRORED) !is 0) rect.x = parent.getClientWidth () - rect.width - rect.x;
1004     int right = rect.x + rect.width;
1005 
1006     int x, w;
1007     parent.ignoreSize = true;
1008     OS.gtk_cell_renderer_get_size (textRenderer, parentHandle, null, null, null, &w, null);
1009     parent.ignoreSize = false;
1010     int buffer;
1011     if (OS.GTK_VERSION < OS.buildVERSION (2, 8, 18) && OS.gtk_tree_view_get_expander_column (parentHandle) is column) {
1012         OS.gtk_widget_style_get1 (parentHandle, OS.expander_size.ptr, &buffer);
1013         rect.x += buffer + TreeItem.EXPANDER_EXTRA_PADDING;
1014     }
1015     /*
1016     * Bug in GTK. In GTK 2.8.x, the cell area is left aligned even
1017     * when the widget is mirrored. The fix is to sum up the indentation
1018     * of the expanders.
1019     */
1020     if ((parent.getStyle () & SWT.MIRRORED) !is 0 && (OS.GTK_VERSION < OS.buildVERSION (2, 10, 0))) {
1021         int depth = OS.gtk_tree_path_get_depth (path);
1022         int expanderSize;
1023         OS.gtk_widget_style_get1 (parentHandle, OS.expander_size.ptr, &expanderSize);
1024         rect.x += depth * (expanderSize + TreeItem.EXPANDER_EXTRA_PADDING);
1025     }
1026     OS.gtk_tree_path_free (path);
1027 
1028     OS.gtk_widget_style_get1 (parentHandle, OS.horizontal_separator.ptr, &buffer);
1029     int horizontalSeparator = buffer;
1030     rect.x += horizontalSeparator;
1031     if (OS.GTK_VERSION >= OS.buildVERSION (2, 1, 3)) {
1032         OS.gtk_tree_view_column_cell_get_position (column, textRenderer, &x, null);
1033         rect.x += x;
1034     } else {
1035         if ((parent.style & SWT.CHECK) !is 0) {
1036             OS.gtk_cell_renderer_get_size (parent.checkRenderer, parentHandle, null, null, null, &w, null);
1037             rect.x += w + horizontalSeparator;
1038         }
1039         OS.gtk_cell_renderer_get_size (pixbufRenderer, parentHandle, null, null, null, &w, null);
1040         rect.x += w + horizontalSeparator;
1041     }
1042     if (parent.columnCount > 0) {
1043         if (rect.x + rect.width > right) {
1044             rect.width = Math.max (0, right - rect.x);
1045         }
1046     }
1047     int width = OS.gtk_tree_view_column_get_visible (column) ? rect.width + 1 : 0;
1048     return new Rectangle (rect.x, rect.y, width, rect.height + 1);
1049 }
1050 
1051 /**
1052  * Searches the receiver's list starting at the first item
1053  * (index 0) until an item is found that is equal to the
1054  * argument, and returns the index of that item. If no item
1055  * is found, returns -1.
1056  *
1057  * @param item the search item
1058  * @return the index of the item
1059  *
1060  * @exception IllegalArgumentException <ul>
1061  *    <li>ERROR_NULL_ARGUMENT - if the item is null</li>
1062  *    <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li>
1063  * </ul>
1064  * @exception SWTException <ul>
1065  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1066  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1067  * </ul>
1068  *
1069  * @since 3.1
1070  */
1071 public int indexOf (TreeItem item) {
1072     checkWidget();
1073     if (item is null) error (SWT.ERROR_NULL_ARGUMENT);
1074     if (item.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
1075     int index = -1;
1076     bool isParent = false;
1077     auto currentPath = OS.gtk_tree_model_get_path (parent.modelHandle, handle);
1078     auto parentPath = OS.gtk_tree_model_get_path (parent.modelHandle, item.handle);
1079     int depth = OS.gtk_tree_path_get_depth (parentPath);
1080     if (depth > 1 && OS.gtk_tree_path_up(parentPath)) {
1081         if (OS.gtk_tree_path_compare(currentPath, parentPath) is 0) isParent = true;
1082     }
1083     OS.gtk_tree_path_free (currentPath);
1084     OS.gtk_tree_path_free (parentPath);
1085     if (!isParent) return index;
1086     auto path = OS.gtk_tree_model_get_path (parent.modelHandle, item.handle);
1087     if (depth > 1) {
1088         auto indices = OS.gtk_tree_path_get_indices (path);
1089         if (indices !is null) {
1090             int[] temp = indices[ 0 .. depth];
1091             index = temp[temp.length - 1];
1092         }
1093     }
1094     OS.gtk_tree_path_free (path);
1095     return index;
1096 }
1097 
1098 void redraw () {
1099     auto parentHandle = parent.handle;
1100     if ((OS.GTK_WIDGET_FLAGS (parentHandle) & OS.GTK_REALIZED) !is 0) {
1101         auto path = OS.gtk_tree_model_get_path (parent.modelHandle, handle);
1102         GdkRectangle rect;
1103         OS.gtk_tree_view_get_cell_area (parentHandle, path, null, &rect);
1104         OS.gtk_tree_path_free (path);
1105         auto window = OS.gtk_tree_view_get_bin_window (parentHandle);
1106         rect.x = 0;
1107         int w, h;
1108         OS.gdk_drawable_get_size (window, &w, &h);
1109         rect.width = w;
1110         OS.gdk_window_invalidate_rect (window, &rect, false);
1111     }
1112 }
1113 
1114 override void releaseChildren (bool destroy) {
1115     if (destroy) {
1116         parent.releaseItems (cast(GtkTreeIter*)handle);
1117     }
1118     super.releaseChildren (destroy);
1119 }
1120 
1121 override void releaseHandle () {
1122     if (handle !is null) OS.g_free (handle);
1123     handle = null;
1124     super.releaseHandle ();
1125     parent = null;
1126 }
1127 
1128 override void releaseWidget () {
1129     super.releaseWidget ();
1130     font = null;
1131     cellFont = null;
1132 }
1133 
1134 /**
1135  * Removes all of the items from the receiver.
1136  * <p>
1137  * @exception SWTException <ul>
1138  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1139  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1140  * </ul>
1141  *
1142  * @since 3.1
1143  */
1144 public void removeAll () {
1145     checkWidget ();
1146     int length = OS.gtk_tree_model_iter_n_children (parent.modelHandle, handle);
1147     if (length is 0) return;
1148     GtkTreeIter iter;
1149     int index;
1150     while (OS.gtk_tree_model_iter_children (parent.modelHandle, &iter, handle)) {
1151         OS.gtk_tree_model_get1 (parent.modelHandle, &iter, Tree.ID_COLUMN, cast(void**)&index);
1152         if (index !is -1) {
1153             TreeItem item = parent.items [index];
1154             if (item !is null && !item.isDisposed ()) {
1155                 item.dispose ();
1156             }
1157         }
1158     }
1159 }
1160 
1161 /**
1162  * Sets the receiver's background color to the color specified
1163  * by the argument, or to the default system color for the item
1164  * if the argument is null.
1165  *
1166  * @param color the new color (or null)
1167  *
1168  * @exception IllegalArgumentException <ul>
1169  *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
1170  * </ul>
1171  * @exception SWTException <ul>
1172  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1173  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1174  * </ul>
1175  *
1176  * @since 2.0
1177  *
1178  */
1179 public void setBackground (Color color) {
1180     checkWidget ();
1181     if (color !is null && color.isDisposed ()) {
1182         SWT.error (SWT.ERROR_INVALID_ARGUMENT);
1183     }
1184     if (_getBackground ().opEquals (color)) return;
1185     GdkColor* gdkColor = color !is null ? color.handle : null;
1186     OS.gtk_tree_store_set1 (parent.modelHandle, cast(GtkTreeIter*)handle, Tree.BACKGROUND_COLUMN, gdkColor);
1187     /*
1188     * Bug in GTK.  When using fixed-height-mode,
1189     * row changes do not cause the row to be repainted.  The fix is to
1190     * invalidate the row when it is cleared.
1191     */
1192     if ((parent.style & SWT.VIRTUAL) !is 0) {
1193         if (OS.GTK_VERSION >= OS.buildVERSION (2, 3, 2) && OS.GTK_VERSION < OS.buildVERSION (2, 6, 3)) {
1194             redraw ();
1195         }
1196     }
1197     cached = true;
1198 }
1199 
1200 /**
1201  * Sets the background color at the given column index in the receiver
1202  * to the color specified by the argument, or to the default system color for the item
1203  * if the argument is null.
1204  *
1205  * @param index the column index
1206  * @param color the new color (or null)
1207  *
1208  * @exception IllegalArgumentException <ul>
1209  *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
1210  * </ul>
1211  * @exception SWTException <ul>
1212  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1213  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1214  * </ul>
1215  *
1216  * @since 3.1
1217  *
1218  */
1219 public void setBackground (int index, Color color) {
1220     checkWidget ();
1221     if (color !is null && color.isDisposed ()) {
1222         SWT.error (SWT.ERROR_INVALID_ARGUMENT);
1223     }
1224     if (_getBackground (index).opEquals (color)) return;
1225     int count = Math.max (1, parent.getColumnCount ());
1226     if (0 > index || index > count - 1) return;
1227     int modelIndex = parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex;
1228     GdkColor* gdkColor = color !is null ? color.handle : null;
1229     OS.gtk_tree_store_set1 (parent.modelHandle, cast(GtkTreeIter*)handle, modelIndex + Tree.CELL_BACKGROUND, gdkColor);
1230     /*
1231     * Bug in GTK.  When using fixed-height-mode,
1232     * row changes do not cause the row to be repainted.  The fix is to
1233     * invalidate the row when it is cleared.
1234     */
1235     if ((parent.style & SWT.VIRTUAL) !is 0) {
1236         if (OS.GTK_VERSION >= OS.buildVERSION (2, 3, 2) && OS.GTK_VERSION < OS.buildVERSION (2, 6, 3)) {
1237             redraw ();
1238         }
1239     }
1240     cached = true;
1241 
1242     if (color !is null) {
1243         bool customDraw = (parent.columnCount is 0)  ? parent.firstCustomDraw : parent.columns [index].customDraw;
1244         if (!customDraw) {
1245             if ((parent.style & SWT.VIRTUAL) is 0) {
1246                 auto parentHandle = parent.handle;
1247                 GtkTreeViewColumn* column;
1248                 if (parent.columnCount > 0) {
1249                     column = cast(GtkTreeViewColumn*)parent.columns [index].handle;
1250                 } else {
1251                     column = OS.gtk_tree_view_get_column (parentHandle, index);
1252                 }
1253                 if (column is null) return;
1254                 auto textRenderer = parent.getTextRenderer (column);
1255                 auto imageRenderer = parent.getPixbufRenderer (column);
1256                 display.doCellDataProc( parentHandle, cast(GtkTreeViewColumn*)column, cast(GtkCellRenderer*)textRenderer );
1257                 display.doCellDataProc( parentHandle, cast(GtkTreeViewColumn*)column, cast(GtkCellRenderer*)imageRenderer );
1258             }
1259             if (parent.columnCount is 0) {
1260                 parent.firstCustomDraw = true;
1261             } else {
1262                 parent.columns [index].customDraw = true;
1263             }
1264         }
1265     }
1266 }
1267 
1268 /**
1269  * Sets the checked state of the receiver.
1270  * <p>
1271  *
1272  * @param checked the new checked state
1273  *
1274  * @exception SWTException <ul>
1275  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1276  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1277  * </ul>
1278  */
1279 public void setChecked (bool checked) {
1280     checkWidget();
1281     if ((parent.style & SWT.CHECK) is 0) return;
1282     if (_getChecked () is checked) return;
1283     OS.gtk_tree_store_set1 (parent.modelHandle, cast(GtkTreeIter*)handle, Tree.CHECKED_COLUMN, cast(void*)cast(int)checked);
1284     /*
1285     * GTK+'s "inconsistent" state does not match SWT's concept of grayed.  To
1286     * show checked+grayed differently from unchecked+grayed, we must toggle the
1287     * grayed state on check and uncheck.
1288     */
1289     OS.gtk_tree_store_set1 (parent.modelHandle, cast(GtkTreeIter*)handle, Tree.GRAYED_COLUMN, cast(void*)cast(int)( !checked ? false : grayed));
1290     cached = true;
1291 }
1292 
1293 /**
1294  * Sets the expanded state of the receiver.
1295  * <p>
1296  *
1297  * @param expanded the new expanded state
1298  *
1299  * @exception SWTException <ul>
1300  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1301  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1302  * </ul>
1303  */
1304 public void setExpanded (bool expanded) {
1305     checkWidget();
1306     auto path = OS.gtk_tree_model_get_path (parent.modelHandle, handle);
1307     if (expanded) {
1308         OS.g_signal_handlers_block_matched (parent.handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udTEST_EXPAND_ROW);
1309         OS.gtk_tree_view_expand_row (parent.handle, path, false);
1310         OS.g_signal_handlers_unblock_matched (parent.handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udTEST_EXPAND_ROW);
1311     } else {
1312         OS.g_signal_handlers_block_matched (parent.handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udTEST_COLLAPSE_ROW);
1313         OS.gtk_widget_realize (parent.handle);
1314         OS.gtk_tree_view_collapse_row (parent.handle, path);
1315         OS.g_signal_handlers_unblock_matched (parent.handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udTEST_COLLAPSE_ROW);
1316     }
1317     OS.gtk_tree_path_free (path);
1318     cached = true;
1319 }
1320 
1321 
1322 /**
1323  * Sets the font that the receiver will use to paint textual information
1324  * for this item to the font specified by the argument, or to the default font
1325  * for that kind of control if the argument is null.
1326  *
1327  * @param font the new font (or null)
1328  *
1329  * @exception IllegalArgumentException <ul>
1330  *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
1331  * </ul>
1332  * @exception SWTException <ul>
1333  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1334  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1335  * </ul>
1336  *
1337  * @since 3.0
1338  */
1339 public void setFont (Font font){
1340     checkWidget ();
1341     if (font !is null && font.isDisposed ()) {
1342         SWT.error (SWT.ERROR_INVALID_ARGUMENT);
1343     }
1344     Font oldFont = this.font;
1345     if (oldFont is font) return;
1346     this.font = font;
1347     if (oldFont !is null && oldFont.opEquals (font)) return;
1348     void* fontHandle = font !is null ? font.handle : null;
1349     OS.gtk_tree_store_set1 (parent.modelHandle, cast(GtkTreeIter*)handle, Tree.FONT_COLUMN, fontHandle);
1350     /*
1351     * Bug in GTK.  When using fixed-height-mode,
1352     * row changes do not cause the row to be repainted.  The fix is to
1353     * invalidate the row when it is cleared.
1354     */
1355     if ((parent.style & SWT.VIRTUAL) !is 0) {
1356         if (OS.GTK_VERSION >= OS.buildVERSION (2, 3, 2) && OS.GTK_VERSION < OS.buildVERSION (2, 6, 3)) {
1357             redraw ();
1358         }
1359     }
1360     cached = true;
1361 }
1362 
1363 /**
1364  * Sets the font that the receiver will use to paint textual information
1365  * for the specified cell in this item to the font specified by the
1366  * argument, or to the default font for that kind of control if the
1367  * argument is null.
1368  *
1369  * @param index the column index
1370  * @param font the new font (or null)
1371  *
1372  * @exception IllegalArgumentException <ul>
1373  *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
1374  * </ul>
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>
1378  * </ul>
1379  *
1380  * @since 3.1
1381  */
1382 public void setFont (int index, Font font) {
1383     checkWidget ();
1384     if (font !is null && font.isDisposed ()) {
1385         SWT.error (SWT.ERROR_INVALID_ARGUMENT);
1386     }
1387     int count = Math.max (1, parent.getColumnCount ());
1388     if (0 > index || index > count - 1) return;
1389     if (cellFont is null) {
1390         if (font is null) return;
1391         cellFont = new Font [count];
1392     }
1393     Font oldFont = cellFont [index];
1394     if (oldFont is font) return;
1395     cellFont [index] = font;
1396     if (oldFont !is null && oldFont.opEquals (font)) return;
1397 
1398     int modelIndex = parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex;
1399     auto fontHandle  = font !is null ? font.handle : null;
1400     OS.gtk_tree_store_set1 (parent.modelHandle, cast(GtkTreeIter*)handle, modelIndex + Tree.CELL_FONT, fontHandle);
1401     /*
1402     * Bug in GTK.  When using fixed-height-mode,
1403     * row changes do not cause the row to be repainted.  The fix is to
1404     * invalidate the row when it is cleared.
1405     */
1406     if ((parent.style & SWT.VIRTUAL) !is 0) {
1407         if (OS.GTK_VERSION >= OS.buildVERSION (2, 3, 2) && OS.GTK_VERSION < OS.buildVERSION (2, 6, 3)) {
1408             redraw ();
1409         }
1410     }
1411     cached = true;
1412 
1413     if (font !is null) {
1414         bool customDraw = (parent.columnCount is 0)  ? parent.firstCustomDraw : parent.columns [index].customDraw;
1415         if (!customDraw) {
1416             if ((parent.style & SWT.VIRTUAL) is 0) {
1417                 auto parentHandle = parent.handle;
1418                 GtkTreeViewColumn* column;
1419                 if (parent.columnCount > 0) {
1420                     column = cast(GtkTreeViewColumn*)parent.columns [index].handle;
1421                 } else {
1422                     column = OS.gtk_tree_view_get_column (parentHandle, index);
1423                 }
1424                 if (column is null) return;
1425                 auto textRenderer = parent.getTextRenderer (column);
1426                 auto imageRenderer = parent.getPixbufRenderer (column);
1427                 display.doCellDataProc( parentHandle, cast(GtkTreeViewColumn*)column, cast(GtkCellRenderer*)textRenderer );
1428                 display.doCellDataProc( parentHandle, cast(GtkTreeViewColumn*)column, cast(GtkCellRenderer*)imageRenderer );
1429             }
1430             if (parent.columnCount is 0) {
1431                 parent.firstCustomDraw = true;
1432             } else {
1433                 parent.columns [index].customDraw = true;
1434             }
1435         }
1436     }
1437 }
1438 
1439 /**
1440  * Sets the receiver's foreground color to the color specified
1441  * by the argument, or to the default system color for the item
1442  * if the argument is null.
1443  *
1444  * @param color the new color (or null)
1445  *
1446  * @since 2.0
1447  *
1448  * @exception IllegalArgumentException <ul>
1449  *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
1450  * </ul>
1451  * @exception SWTException <ul>
1452  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1453  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1454  * </ul>
1455  *
1456  * @since 2.0
1457  *
1458  */
1459 public void setForeground (Color color){
1460     checkWidget ();
1461     if (color !is null && color.isDisposed ()) {
1462         SWT.error (SWT.ERROR_INVALID_ARGUMENT);
1463     }
1464     if (_getForeground ().opEquals (color)) return;
1465     GdkColor *gdkColor = color !is null ? color.handle : null;
1466     OS.gtk_tree_store_set1 (parent.modelHandle, cast(GtkTreeIter*)handle, Tree.FOREGROUND_COLUMN, gdkColor);
1467     /*
1468     * Bug in GTK.  When using fixed-height-mode,
1469     * row changes do not cause the row to be repainted.  The fix is to
1470     * invalidate the row when it is cleared.
1471     */
1472     if ((parent.style & SWT.VIRTUAL) !is 0) {
1473         if (OS.GTK_VERSION >= OS.buildVERSION (2, 3, 2) && OS.GTK_VERSION < OS.buildVERSION (2, 6, 3)) {
1474             redraw ();
1475         }
1476     }
1477     cached = true;
1478 }
1479 
1480 /**
1481  * Sets the foreground color at the given column index in the receiver
1482  * to the color specified by the argument, or to the default system color for the item
1483  * if the argument is null.
1484  *
1485  * @param index the column index
1486  * @param color the new color (or null)
1487  *
1488  * @exception IllegalArgumentException <ul>
1489  *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
1490  * </ul>
1491  * @exception SWTException <ul>
1492  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1493  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1494  * </ul>
1495  *
1496  * @since 3.1
1497  *
1498  */
1499 public void setForeground (int index, Color color){
1500     checkWidget ();
1501     if (color !is null && color.isDisposed ()) {
1502         SWT.error (SWT.ERROR_INVALID_ARGUMENT);
1503     }
1504     if (_getForeground (index).opEquals (color)) return;
1505     int count = Math.max (1, parent.getColumnCount ());
1506     if (0 > index || index > count - 1) return;
1507     int modelIndex = parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex;
1508     GdkColor *gdkColor = color !is null ? color.handle : null;
1509     OS.gtk_tree_store_set1 (parent.modelHandle, cast(GtkTreeIter*)handle, modelIndex + Tree.CELL_FOREGROUND, gdkColor);
1510     /*
1511     * Bug in GTK.  When using fixed-height-mode,
1512     * row changes do not cause the row to be repainted.  The fix is to
1513     * invalidate the row when it is cleared.
1514     */
1515     if ((parent.style & SWT.VIRTUAL) !is 0) {
1516         if (OS.GTK_VERSION >= OS.buildVERSION (2, 3, 2) && OS.GTK_VERSION < OS.buildVERSION (2, 6, 3)) {
1517             redraw ();
1518         }
1519     }
1520     cached = true;
1521 
1522     if (color !is null) {
1523         bool customDraw = (parent.columnCount is 0)  ? parent.firstCustomDraw : parent.columns [index].customDraw;
1524         if (!customDraw) {
1525             if ((parent.style & SWT.VIRTUAL) is 0) {
1526                 auto parentHandle = parent.handle;
1527                 GtkTreeViewColumn* column;
1528                 if (parent.columnCount > 0) {
1529                     column = cast(GtkTreeViewColumn*)parent.columns [index].handle;
1530                 } else {
1531                     column = OS.gtk_tree_view_get_column (parentHandle, index);
1532                 }
1533                 if (column is null) return;
1534                 auto textRenderer = parent.getTextRenderer (column);
1535                 auto imageRenderer = parent.getPixbufRenderer (column);
1536                 display.doCellDataProc( parentHandle, cast(GtkTreeViewColumn*)column, cast(GtkCellRenderer*)textRenderer );
1537                 display.doCellDataProc( parentHandle, cast(GtkTreeViewColumn*)column, cast(GtkCellRenderer*)imageRenderer );
1538             }
1539             if (parent.columnCount is 0) {
1540                 parent.firstCustomDraw = true;
1541             } else {
1542                 parent.columns [index].customDraw = true;
1543             }
1544         }
1545     }
1546 }
1547 
1548 /**
1549  * Sets the grayed state of the checkbox for this item.  This state change
1550  * only applies if the Tree was created with the SWT.CHECK style.
1551  *
1552  * @param grayed the new grayed state of the checkbox
1553  *
1554  * @exception SWTException <ul>
1555  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1556  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1557  * </ul>
1558  */
1559 public void setGrayed (bool grayed) {
1560     checkWidget();
1561     if ((parent.style & SWT.CHECK) is 0) return;
1562     if (this.grayed is grayed) return;
1563     this.grayed = grayed;
1564     /*
1565     * GTK+'s "inconsistent" state does not match SWT's concept of grayed.
1566     * Render checked+grayed as "inconsistent", unchecked+grayed as blank.
1567     */
1568     void* ptr;
1569     OS.gtk_tree_model_get1 (parent.modelHandle, handle, Tree.CHECKED_COLUMN, &ptr);
1570     OS.gtk_tree_store_set1 (parent.modelHandle, cast(GtkTreeIter*)handle, Tree.GRAYED_COLUMN, cast(void*)cast(int)( ptr is null ? false : grayed));
1571     cached = true;
1572 }
1573 
1574 /**
1575  * Sets the receiver's image at a column.
1576  *
1577  * @param index the column index
1578  * @param image the new image
1579  *
1580  * @exception IllegalArgumentException <ul>
1581  *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
1582  * </ul>
1583  * @exception SWTException <ul>
1584  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1585  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1586  * </ul>
1587  *
1588  * @since 3.1
1589  */
1590 public void setImage (int index, Image image) {
1591     checkWidget ();
1592     if (image !is null && image.isDisposed()) {
1593         error(SWT.ERROR_INVALID_ARGUMENT);
1594     }
1595     if (image !is null && image.type is SWT.ICON) {
1596         if (image.opEquals (_getImage (index))) return;
1597     }
1598     int count = Math.max (1, parent.getColumnCount ());
1599     if (0 > index || index > count - 1) return;
1600     GdkPixbuf* pixbuf;
1601     if (image !is null) {
1602         ImageList imageList = parent.imageList;
1603         if (imageList is null) imageList = parent.imageList = new ImageList ();
1604         int imageIndex = imageList.indexOf (image);
1605         if (imageIndex is -1) imageIndex = imageList.add (image);
1606         pixbuf = imageList.getPixbuf (imageIndex);
1607     }
1608     int modelIndex = parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex;
1609     OS.gtk_tree_store_set1 (parent.modelHandle, cast(GtkTreeIter*)handle, modelIndex + Tree.CELL_PIXBUF, pixbuf);
1610     /*
1611     * Bug in GTK.  When using fixed-height-mode,
1612     * row changes do not cause the row to be repainted.  The fix is to
1613     * invalidate the row when the image changes.
1614     */
1615     if ((parent.style & SWT.VIRTUAL) !is 0) {
1616         if (OS.GTK_VERSION >= OS.buildVERSION (2, 3, 2) && OS.GTK_VERSION < OS.buildVERSION (2, 6, 3)) {
1617             if (parent.columnCount is 0) {
1618                 redraw ();
1619             }
1620         }
1621     }
1622     /*
1623     * Bug in GTK.  When using fixed-height-mode, GTK does not recalculate the cell renderer width
1624     * when the image is changed in the model.  The fix is to force it to recalculate the width if
1625     * more space is required.
1626     */
1627     if ((parent.style & SWT.VIRTUAL) !is 0 && parent.currentItem is null) {
1628         if (OS.GTK_VERSION >= OS.buildVERSION (2, 3, 2)) {
1629             if (image !is null) {
1630                 auto parentHandle = parent.handle;
1631                 auto column = OS.gtk_tree_view_get_column (parentHandle, index);
1632                 int w;
1633                 auto pixbufRenderer = parent.getPixbufRenderer(column);
1634                 OS.gtk_tree_view_column_cell_get_position (column, pixbufRenderer, null, &w);
1635                 if (w < image.getBounds().width) {
1636                     /*
1637                      * There is no direct way to clear the cell renderer width so we
1638                      * are relying on the fact that it is done as part of modifying
1639                      * the style.
1640                      */
1641                     auto style = OS.gtk_widget_get_modifier_style (parentHandle);
1642                     parent.modifyStyle (parentHandle, style);
1643                 }
1644             }
1645         }
1646     }
1647     cached = true;
1648 }
1649 
1650 public override void setImage (Image image) {
1651     checkWidget ();
1652     setImage (0, image);
1653 }
1654 
1655 /**
1656  * Sets the image for multiple columns in the tree.
1657  *
1658  * @param images the array of new images
1659  *
1660  * @exception IllegalArgumentException <ul>
1661  *    <li>ERROR_INVALID_ARGUMENT - if one of the images 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 (Image [] images) {
1671     checkWidget ();
1672     // SWT extension: allow null for zero length string
1673     //if (images is null) error (SWT.ERROR_NULL_ARGUMENT);
1674     for (int i=0; i<images.length; i++) {
1675         setImage (i, images [i]);
1676     }
1677 }
1678 
1679 /**
1680  * Sets the number of child items contained in the receiver.
1681  *
1682  * @param count the number of items
1683  *
1684  * @exception SWTException <ul>
1685  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1686  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1687  * </ul>
1688  *
1689  * @since 3.2
1690  */
1691 public void setItemCount (int count) {
1692     checkWidget ();
1693     count = Math.max (0, count);
1694     parent.setItemCount (cast(GtkTreeIter*)handle, count);
1695 }
1696 
1697 /**
1698  * Sets the receiver's text at a column
1699  *
1700  * @param index the column index
1701  * @param string the new text
1702  *
1703  * @exception SWTException <ul>
1704  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1705  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1706  * </ul>
1707  *
1708  * @since 3.1
1709  */
1710 public void setText (int index, String string) {
1711     checkWidget ();
1712     // SWT extension: allow null for zero length string
1713     //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
1714     if (_getText (index).equals (string)) return;
1715     int count = Math.max (1, parent.getColumnCount ());
1716     if (0 > index || index > count - 1) return;
1717     char* buffer = toStringz(string);
1718     int modelIndex = parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex;
1719     OS.gtk_tree_store_set1 (parent.modelHandle, cast(GtkTreeIter*)handle, modelIndex + Tree.CELL_TEXT, buffer);
1720     /*
1721     * Bug in GTK.  When using fixed-height-mode,
1722     * row changes do not cause the row to be repainted.  The fix is to
1723     * invalidate the row when the text changes.
1724     */
1725     if ((parent.style & SWT.VIRTUAL) !is 0) {
1726         if (OS.GTK_VERSION >= OS.buildVERSION (2, 3, 2) && OS.GTK_VERSION < OS.buildVERSION (2, 6, 3)) {
1727             redraw ();
1728         }
1729     }
1730     cached = true;
1731 }
1732 
1733 public override void setText (String string) {
1734     checkWidget ();
1735     setText (0, string);
1736 }
1737 
1738 /**
1739  * Sets the text for multiple columns in the tree.
1740  *
1741  * @param strings the array of new strings
1742  *
1743  * @exception SWTException <ul>
1744  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1745  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1746  * </ul>
1747  *
1748  * @since 3.1
1749  */
1750 public void setText (String [] strings) {
1751     checkWidget ();
1752     // SWT extension: allow null for zero length string
1753     //if (strings is null) error (SWT.ERROR_NULL_ARGUMENT);
1754     for (int i=0; i<strings.length; i++) {
1755         String string = strings [i];
1756         if (string !is null) setText (i, string);
1757     }
1758 }
1759 }