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.ExpandItem;
14 
15 import java.lang.all;
16 
17 
18 import org.eclipse.swt.SWT;
19 import org.eclipse.swt.SWTException;
20 import org.eclipse.swt.graphics.GC;
21 import org.eclipse.swt.graphics.Image;
22 import org.eclipse.swt.graphics.Point;
23 import org.eclipse.swt.graphics.Rectangle;
24 import org.eclipse.swt.internal.Converter;
25 import org.eclipse.swt.internal.gtk.OS;
26 import org.eclipse.swt.widgets.Item;
27 import org.eclipse.swt.widgets.Control;
28 import org.eclipse.swt.widgets.Display;
29 import org.eclipse.swt.widgets.ExpandBar;
30 import org.eclipse.swt.widgets.ImageList;
31 import org.eclipse.swt.widgets.Event;
32 
33 
34 /**
35  * Instances of this class represent a selectable user interface object
36  * that represents a expandable item in a expand bar.
37  * <p>
38  * <dl>
39  * <dt><b>Styles:</b></dt>
40  * <dd>(none)</dd>
41  * <dt><b>Events:</b></dt>
42  * <dd>(none)</dd>
43  * </dl>
44  * </p><p>
45  * IMPORTANT: This class is <em>not</em> intended to be subclassed.
46  * </p>
47  *
48  * @see ExpandBar
49  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
50  *
51  * @since 3.2
52  */
53 public class ExpandItem : Item {
54 
55     alias Item.setForegroundColor setForegroundColor;
56     alias Item.windowProc windowProc;
57 
58     ExpandBar parent;
59     Control control;
60     ImageList imageList;
61     GtkWidget* clientHandle, boxHandle, labelHandle, imageHandle;
62     bool expanded;
63     int x, y, width, height;
64     int imageHeight, imageWidth;
65     static const int TEXT_INSET = 6;
66     static const int BORDER = 1;
67     static const int CHEVRON_SIZE = 24;
68 
69 /**
70  * Constructs a new instance of this class given its parent
71  * and a style value describing its behavior and appearance.
72  * <p>
73  * The style value is either one of the style constants defined in
74  * class <code>SWT</code> which is applicable to instances of this
75  * class, or must be built by <em>bitwise OR</em>'ing together
76  * (that is, using the <code>int</code> "|" operator) two or more
77  * of those <code>SWT</code> style constants. The class description
78  * lists the style constants that are applicable to the class.
79  * Style bits are also inherited from superclasses.
80  * </p>
81  *
82  * @param parent a composite control which will be the parent of the new instance (cannot be null)
83  * @param style the style of control to construct
84  *
85  * @exception IllegalArgumentException <ul>
86  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
87  * </ul>
88  * @exception SWTException <ul>
89  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
90  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
91  * </ul>
92  *
93  * @see Widget#checkSubclass
94  * @see Widget#getStyle
95  */
96 public this (ExpandBar parent, int style) {
97     super (parent, style);
98     this.parent = parent;
99     createWidget (parent.getItemCount ());
100 }
101 
102 /**
103  * Constructs a new instance of this class given its parent, a
104  * style value describing its behavior and appearance, and the index
105  * at which to place it in the items maintained by its parent.
106  * <p>
107  * The style value is either one of the style constants defined in
108  * class <code>SWT</code> which is applicable to instances of this
109  * class, or must be built by <em>bitwise OR</em>'ing together
110  * (that is, using the <code>int</code> "|" operator) two or more
111  * of those <code>SWT</code> style constants. The class description
112  * lists the style constants that are applicable to the class.
113  * Style bits are also inherited from superclasses.
114  * </p>
115  *
116  * @param parent a composite control which will be the parent of the new instance (cannot be null)
117  * @param style the style of control to construct
118  * @param index the zero-relative index to store the receiver in its parent
119  *
120  * @exception IllegalArgumentException <ul>
121  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
122  *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
123  * </ul>
124  * @exception SWTException <ul>
125  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
126  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
127  * </ul>
128  *
129  * @see Widget#checkSubclass
130  * @see Widget#getStyle
131  */
132 public this (ExpandBar parent, int style, int index) {
133     super (parent, style);
134     this.parent = parent;
135     createWidget (index);
136 }
137 
138 protected override void checkSubclass () {
139     if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
140 }
141 
142 override void createHandle (int index) {
143     if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) {
144         state |= HANDLE;
145         handle = OS.gtk_expander_new (null);
146         if (handle is null) error (SWT.ERROR_NO_HANDLES);
147         clientHandle = cast(GtkWidget*)OS.g_object_new (display.gtk_fixed_get_type (), null);
148         if (clientHandle is null) error (SWT.ERROR_NO_HANDLES);
149         OS.gtk_container_add (handle, clientHandle);
150         boxHandle = cast(GtkWidget*)OS.gtk_hbox_new (false, 4);
151         if (boxHandle is null) error (SWT.ERROR_NO_HANDLES);
152         labelHandle = cast(GtkWidget*)OS.gtk_label_new (null);
153         if (labelHandle is null) error (SWT.ERROR_NO_HANDLES);
154         imageHandle = cast(GtkWidget*)OS.gtk_image_new ();
155         if (imageHandle is null) error (SWT.ERROR_NO_HANDLES);
156         OS.gtk_container_add (boxHandle, imageHandle);
157         OS.gtk_container_add (boxHandle, labelHandle);
158         OS.gtk_expander_set_label_widget (handle, boxHandle);
159         OS.GTK_WIDGET_SET_FLAGS (handle, OS.GTK_CAN_FOCUS);
160     }
161 }
162 
163 override void createWidget (int index) {
164     super.createWidget (index);
165     showWidget (index);
166     parent.createItem (this, style, index);
167 }
168 
169 override void deregister() {
170     super.deregister();
171     if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) {
172         display.removeWidget (clientHandle);
173         display.removeWidget (boxHandle);
174         display.removeWidget (labelHandle);
175         display.removeWidget (imageHandle);
176     }
177 }
178 
179 override void destroyWidget () {
180     parent.destroyItem (this);
181     super.destroyWidget ();
182 }
183 
184 void drawChevron (GC gc, int x, int y) {
185     int [] polyline1, polyline2;
186     if (expanded) {
187         int px = x + 4 + 5;
188         int py = y + 4 + 7;
189         polyline1 = [
190                 px,py, px+1,py, px+1,py-1, px+2,py-1, px+2,py-2, px+3,py-2, px+3,py-3,
191                 px+3,py-2, px+4,py-2, px+4,py-1, px+5,py-1, px+5,py, px+6,py];
192         py += 4;
193         polyline2 = [
194                 px,py, px+1,py, px+1,py-1, px+2,py-1, px+2,py-2, px+3,py-2, px+3,py-3,
195                 px+3,py-2, px+4,py-2, px+4,py-1,  px+5,py-1, px+5,py, px+6,py];
196     } else {
197         int px = x + 4 + 5;
198         int py = y + 4 + 4;
199         polyline1 = [
200                 px,py, px+1,py, px+1,py+1, px+2,py+1, px+2,py+2, px+3,py+2, px+3,py+3,
201                 px+3,py+2, px+4,py+2, px+4,py+1,  px+5,py+1, px+5,py, px+6,py];
202         py += 4;
203         polyline2 = [
204                 px,py, px+1,py, px+1,py+1, px+2,py+1, px+2,py+2, px+3,py+2, px+3,py+3,
205                 px+3,py+2, px+4,py+2, px+4,py+1,  px+5,py+1, px+5,py, px+6,py];
206     }
207     gc.setForeground (display.getSystemColor (SWT.COLOR_TITLE_FOREGROUND));
208     gc.drawPolyline (polyline1);
209     gc.drawPolyline (polyline2);
210 }
211 
212 void drawItem (GC gc, bool drawFocus) {
213     int headerHeight = parent.getBandHeight ();
214     Display display = getDisplay ();
215     gc.setForeground (display.getSystemColor (SWT.COLOR_TITLE_BACKGROUND));
216     gc.setBackground (display.getSystemColor (SWT.COLOR_TITLE_BACKGROUND_GRADIENT));
217     gc.fillGradientRectangle (x, y, width, headerHeight, true);
218     if (expanded) {
219         gc.setForeground (display.getSystemColor (SWT.COLOR_TITLE_BACKGROUND_GRADIENT));
220         gc.drawLine (x, y + headerHeight, x, y + headerHeight + height - 1);
221         gc.drawLine (x, y + headerHeight + height - 1, x + width - 1, y + headerHeight + height - 1);
222         gc.drawLine (x + width - 1, y + headerHeight + height - 1, x + width - 1, y + headerHeight);
223     }
224     int drawX = x;
225     if (image !is null) {
226         drawX += ExpandItem.TEXT_INSET;
227         if (imageHeight > headerHeight) {
228             gc.drawImage (image, drawX, y + headerHeight - imageHeight);
229         } else {
230             gc.drawImage (image, drawX, y + (headerHeight - imageHeight) / 2);
231         }
232         drawX += imageWidth;
233     }
234     if (text.length > 0) {
235         drawX += ExpandItem.TEXT_INSET;
236         Point size = gc.stringExtent (text);
237         gc.setForeground (parent.getForeground ());
238         gc.drawString (text, drawX, y + (headerHeight - size.y) / 2, true);
239     }
240     int chevronSize = ExpandItem.CHEVRON_SIZE;
241     drawChevron (gc, x + width - chevronSize, y + (headerHeight - chevronSize) / 2);
242     if (drawFocus) {
243         gc.drawFocus (x + 1, y + 1, width - 2, headerHeight - 2);
244     }
245 }
246 
247 /**
248  * Returns the control that is shown when the item is expanded.
249  * If no control has been set, return <code>null</code>.
250  *
251  * @return the control
252  *
253  * @exception SWTException <ul>
254  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
255  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
256  * </ul>
257  */
258 public Control getControl () {
259     checkWidget ();
260     return control;
261 }
262 
263 /**
264  * Returns <code>true</code> if the receiver is expanded,
265  * and false otherwise.
266  *
267  * @return the expanded state
268  *
269  * @exception SWTException <ul>
270  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
271  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
272  * </ul>
273  */
274 public bool getExpanded () {
275     checkWidget ();
276     return expanded;
277 }
278 
279 /**
280  * Returns the height of the receiver's header
281  *
282  * @return the height of the header
283  *
284  * @exception SWTException <ul>
285  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
286  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
287  * </ul>
288  */
289 public int getHeaderHeight () {
290     checkWidget ();
291     if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) {
292         return OS.GTK_WIDGET_HEIGHT (handle) - (expanded ? height : 0);
293     }
294     return Math.max (parent.getBandHeight (), imageHeight);
295 }
296 
297 /**
298  * Gets the height of the receiver.
299  *
300  * @return the height
301  *
302  * @exception SWTException <ul>
303  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
304  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
305  * </ul>
306  */
307 public int getHeight () {
308     checkWidget ();
309     return height;
310 }
311 
312 /**
313  * Returns the receiver's parent, which must be a <code>ExpandBar</code>.
314  *
315  * @return the receiver's parent
316  *
317  * @exception SWTException <ul>
318  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
319  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
320  * </ul>
321  */
322 public ExpandBar getParent () {
323     checkWidget();
324     return parent;
325 }
326 
327 int getPreferredWidth (GC gc) {
328     int width = ExpandItem.TEXT_INSET * 2 + ExpandItem.CHEVRON_SIZE;
329     if (image !is null) {
330         width += ExpandItem.TEXT_INSET + imageWidth;
331     }
332     if (text.length > 0) {
333         width += gc.stringExtent (text).x;
334     }
335     return width;
336 }
337 
338 override int gtk_activate (GtkWidget* widget) {
339     Event event = new Event ();
340     event.item = this;
341     int type = OS.gtk_expander_get_expanded (handle) ? SWT.Collapse : SWT.Expand;
342     parent.sendEvent (type, event);
343     return 0;
344 }
345 
346 override int gtk_button_press_event (GtkWidget* widget, GdkEventButton* event) {
347     setFocus ();
348     return 0;
349 }
350 
351 override int gtk_focus_out_event (GtkWidget* widget, GdkEventFocus* event) {
352     OS.GTK_WIDGET_UNSET_FLAGS (handle, OS.GTK_CAN_FOCUS);
353     parent.lastFocus = this;
354     return 0;
355 }
356 
357 override int gtk_size_allocate (GtkWidget* widget, ptrdiff_t allocation) {
358     parent.layoutItems (0, false);
359     return 0;
360 }
361 
362 override int gtk_enter_notify_event (GtkWidget* widget, GdkEventCrossing* event) {
363     parent.gtk_enter_notify_event(widget, event);
364     return 0;
365 }
366 
367 bool hasFocus () {
368     return OS.GTK_WIDGET_HAS_FOCUS (handle);
369 }
370 
371 override void hookEvents () {
372     super.hookEvents ();
373     if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) {
374         OS.g_signal_connect_closure (handle, OS.activate.ptr, display.closures [ACTIVATE], false);
375         OS.g_signal_connect_closure (handle, OS.activate.ptr, display.closures [ACTIVATE_INVERSE], true);
376         OS.g_signal_connect_closure_by_id (handle, display.signalIds [BUTTON_PRESS_EVENT], 0, display.closures [BUTTON_PRESS_EVENT], false);
377         OS.g_signal_connect_closure_by_id (handle, display.signalIds [FOCUS_OUT_EVENT], 0, display.closures [FOCUS_OUT_EVENT], false);
378         OS.g_signal_connect_closure (clientHandle, OS.size_allocate.ptr, display.closures [SIZE_ALLOCATE], true);
379         OS.g_signal_connect_closure_by_id (handle, display.signalIds [ENTER_NOTIFY_EVENT], 0, display.closures [ENTER_NOTIFY_EVENT], false);
380     }
381 }
382 
383 void redraw () {
384     if (OS.GTK_VERSION < OS.buildVERSION (2, 4, 0)) {
385         int headerHeight = parent.getBandHeight ();
386         if (imageHeight > headerHeight) {
387             parent.redraw (x + ExpandItem.TEXT_INSET, y + headerHeight - imageHeight, imageWidth, imageHeight, false);
388         }
389         parent.redraw (x, y, width, headerHeight + height, false);
390     }
391 }
392 
393 override void register () {
394     super.register ();
395     if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) {
396         display.addWidget (clientHandle, this);
397         display.addWidget (boxHandle, this);
398         display.addWidget (labelHandle, this);
399         display.addWidget (imageHandle, this);
400     }
401 }
402 
403 override void releaseHandle () {
404     super.releaseHandle ();
405     clientHandle = boxHandle = labelHandle = imageHandle = null;
406     parent = null;
407 }
408 
409 override void releaseWidget () {
410     super.releaseWidget ();
411     if (imageList !is null) imageList.dispose ();
412     if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) {
413         if (parent.lastFocus is this) parent.lastFocus = null;
414     }
415     imageList = null;
416     control = null;
417 }
418 
419 void resizeControl (int yScroll) {
420     if (control !is null && !control.isDisposed ()) {
421         bool visible =cast(bool) OS.gtk_expander_get_expanded (handle);
422         if (visible) {
423             int x = OS.GTK_WIDGET_X (clientHandle);
424             int y = OS.GTK_WIDGET_Y (clientHandle);
425             if (x !is -1 && y !is -1) {
426                 int width = OS.GTK_WIDGET_WIDTH (clientHandle);
427                 int height = OS.GTK_WIDGET_HEIGHT (clientHandle);
428                 int property;
429                 OS.gtk_widget_style_get1 (handle, OS.focus_line_width.ptr, &property);
430                 y += property * 2;
431                 height -= property * 2;
432                 control.setBounds (x, y - yScroll, width, Math.max (0, height), true, true);
433             }
434         }
435         control.setVisible (visible);
436     }
437 }
438 
439 void setBounds (int x, int y, int width, int height, bool move, bool size) {
440     redraw ();
441     int headerHeight = parent.getBandHeight ();
442     if (move) {
443         if (imageHeight > headerHeight) {
444             y += (imageHeight - headerHeight);
445         }
446         this.x = x;
447         this.y = y;
448         redraw ();
449     }
450     if (size) {
451         this.width = width;
452         this.height = height;
453         redraw ();
454     }
455     if (control !is null && !control.isDisposed ()) {
456         if (move) control.setLocation (x + BORDER, y + headerHeight);
457         if (size) control.setSize (Math.max (0, width - 2 * BORDER), Math.max (0, height - BORDER));
458     }
459 }
460 
461 /**
462  * Sets the control that is shown when the item is expanded.
463  *
464  * @param control the new control (or null)
465  *
466  * @exception IllegalArgumentException <ul>
467  *    <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
468  *    <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</li>
469  * </ul>
470  * @exception SWTException <ul>
471  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
472  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
473  * </ul>
474  */
475 public void setControl (Control control) {
476     checkWidget ();
477     if (control !is null) {
478         if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
479         if (control.parent !is parent) error (SWT.ERROR_INVALID_PARENT);
480     }
481     if (this.control is control) return;
482     this.control = control;
483     if (control !is null) {
484         control.setVisible (expanded);
485         if (OS.GTK_VERSION < OS.buildVERSION (2, 4, 0)) {
486             int headerHeight = parent.getBandHeight ();
487             control.setBounds (x + BORDER, y + headerHeight, Math.max (0, width - 2 * BORDER), Math.max (0, height - BORDER));
488         }
489     }
490     if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) {
491         parent.layoutItems (0, true);
492     }
493 }
494 
495 /**
496  * Sets the expanded state of the receiver.
497  *
498  * @param expanded the new expanded state
499  *
500  * @exception SWTException <ul>
501  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
502  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
503  * </ul>
504  */
505 public void setExpanded (bool expanded) {
506     checkWidget ();
507     this.expanded = expanded;
508     if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) {
509         OS.gtk_expander_set_expanded (handle, expanded);
510         parent.layoutItems (0, true);
511     } else {
512         parent.showItem (this);
513     }
514 }
515 
516 bool setFocus () {
517     if (!OS.gtk_widget_get_child_visible (handle)) return false;
518     OS.GTK_WIDGET_SET_FLAGS (handle, OS.GTK_CAN_FOCUS);
519     OS.gtk_widget_grab_focus (handle);
520     bool result = cast(bool)OS.gtk_widget_is_focus (handle);
521     if (!result) OS.GTK_WIDGET_UNSET_FLAGS (handle, OS.GTK_CAN_FOCUS);
522     return result;
523 }
524 
525 void setFontDescription (PangoFontDescription* font) {
526     OS.gtk_widget_modify_font (handle, font);
527     if (labelHandle !is null) OS.gtk_widget_modify_font (labelHandle, font);
528     if (imageHandle !is null) OS.gtk_widget_modify_font (imageHandle, font);
529 }
530 
531 alias Item.setForegroundColor setForegroundColor;
532 void setForegroundColor (GdkColor* color) {
533     setForegroundColor (handle, color);
534     if (labelHandle !is null) setForegroundColor (labelHandle, color);
535     if (imageHandle !is null) setForegroundColor (imageHandle, color);
536 }
537 
538 /**
539  * Sets the height of the receiver. This is height of the item when it is expanded,
540  * excluding the height of the header.
541  *
542  * @param height the new height
543  *
544  * @exception SWTException <ul>
545  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
546  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
547  * </ul>
548  */
549 public void setHeight (int height) {
550     checkWidget ();
551     if (height < 0) return;
552     if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) {
553         this.height = height;
554         OS.gtk_widget_set_size_request (clientHandle, -1, height);
555         parent.layoutItems (0, false);
556     } else {
557         setBounds (0, 0, width, height, false, true);
558         if (expanded) parent.layoutItems (parent.indexOf (this) + 1, true);
559     }
560 }
561 
562 public override void setImage (Image image) {
563     super.setImage (image);
564     if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) {
565         if (imageList !is null) imageList.dispose ();
566         imageList = null;
567         if (image !is null) {
568             if (image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
569             imageList = new ImageList ();
570             int imageIndex = imageList.add (image);
571             auto pixbuf = imageList.getPixbuf (imageIndex);
572             OS.gtk_image_set_from_pixbuf (imageHandle, pixbuf);
573             if (text.length is 0) OS.gtk_widget_hide (labelHandle);
574             OS.gtk_widget_show (imageHandle);
575         } else {
576             OS.gtk_image_set_from_pixbuf (imageHandle, null);
577             OS.gtk_widget_show (labelHandle);
578             OS.gtk_widget_hide (imageHandle);
579         }
580     } else {
581         int oldImageHeight = imageHeight;
582         if (image !is null) {
583             Rectangle bounds = image.getBounds ();
584             imageHeight = bounds.height;
585             imageWidth = bounds.width;
586         } else {
587             imageHeight = imageWidth = 0;
588         }
589         if (oldImageHeight !is imageHeight) {
590             parent.layoutItems (parent.indexOf (this), true);
591         } else {
592             redraw ();
593         }
594     }
595 }
596 
597 override
598 void setOrientation() {
599     super.setOrientation ();
600     if ((parent.style & SWT.RIGHT_TO_LEFT) !is 0) {
601         OS.gtk_widget_set_direction (handle, OS.GTK_TEXT_DIR_RTL);
602         display.doSetDirectionProc(handle, OS.GTK_TEXT_DIR_RTL);
603     }
604 }
605 
606 public override void setText (String string) {
607     super.setText (string);
608     if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) {
609         OS.gtk_label_set_text (labelHandle, toStringz(string));
610     } else {
611         redraw ();
612     }
613 }
614 
615 void showWidget (int index) {
616     if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) {
617         OS.gtk_widget_show (handle);
618         OS.gtk_widget_show (clientHandle);
619         OS.gtk_container_add (parent.handle, handle);
620         OS.gtk_box_set_child_packing (parent.handle, handle, false, false, 0, OS.GTK_PACK_START);
621         if (boxHandle !is null) OS.gtk_widget_show (boxHandle);
622         if (labelHandle !is null) OS.gtk_widget_show (labelHandle);
623     }
624 }
625 
626 override int windowProc (GtkWidget* handle, ptrdiff_t user_data) {
627     switch (user_data) {
628         case ACTIVATE_INVERSE: {
629             expanded = cast(bool)OS.gtk_expander_get_expanded (handle);
630             parent.layoutItems (0, false);
631             return 0;
632         }
633         default:
634     }
635     return super.windowProc (handle, user_data);
636 }
637 }