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.Widget;
14 
15 import org.eclipse.swt.SWT;
16 import java.lang.all;
17 import java.nonstandard.UnsafeUtf;
18 
19 import org.eclipse.swt.events.DisposeListener;
20 import org.eclipse.swt.internal.Converter;
21 import org.eclipse.swt.internal.SWTEventListener;
22 import org.eclipse.swt.internal.gtk.OS;
23 import org.eclipse.swt.widgets.Display;
24 import org.eclipse.swt.widgets.Event;
25 import org.eclipse.swt.widgets.EventTable;
26 import org.eclipse.swt.widgets.Listener;
27 import org.eclipse.swt.widgets.TypedListener;
28 
29 import java.lang.Thread;
30 
31 /**
32  * This class is the abstract superclass of all user interface objects.
33  * Widgets are created, disposed and issue notification to listeners
34  * when events occur which affect them.
35  * <dl>
36  * <dt><b>Styles:</b></dt>
37  * <dd>(none)</dd>
38  * <dt><b>Events:</b></dt>
39  * <dd>Dispose</dd>
40  * </dl>
41  * <p>
42  * IMPORTANT: This class is intended to be subclassed <em>only</em>
43  * within the SWT implementation. However, it has not been marked
44  * final to allow those outside of the SWT development team to implement
45  * patched versions of the class in order to get around specific
46  * limitations in advance of when those limitations can be addressed
47  * by the team.  Any class built using subclassing to access the internals
48  * of this class will likely fail to compile or run between releases and
49  * may be strongly platform specific. Subclassing should not be attempted
50  * without an intimate and detailed understanding of the workings of the
51  * hierarchy. No support is provided for user-written classes which are
52  * implemented as subclasses of this class.
53  * </p>
54  *
55  * @see #checkSubclass
56  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
57  */
58 public abstract class Widget {
59     /**
60      * the handle to the OS resource
61      * (Warning: This field is platform dependent)
62      * <p>
63      * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
64      * public API. It is marked public only so that it can be shared
65      * within the packages provided by SWT. It is not available on all
66      * platforms and should never be accessed from application code.
67      * </p>
68      */
69     public GtkWidget* handle;
70     int style, state;
71     Display display;
72     EventTable eventTable;
73     Object data;
74 
75     /* Global state flags */
76     static const int DISPOSED = 1<<0;
77     static const int CANVAS = 1<<1;
78     static const int KEYED_DATA = 1<<2;
79     static const int HANDLE = 1<<3;
80     static const int DISABLED = 1<<4;
81     static const int MENU = 1<<5;
82     static const int OBSCURED = 1<<6;
83     static const int MOVED = 1<<7;
84     static const int RESIZED = 1<<8;
85     static const int ZERO_WIDTH = 1<<9;
86     static const int ZERO_HEIGHT = 1<<10;
87     static const int HIDDEN = 1<<11;
88     static const int FOREGROUND = 1<<12;
89     static const int BACKGROUND = 1<<13;
90     static const int FONT = 1<<14;
91     static const int PARENT_BACKGROUND = 1<<15;
92     static const int THEME_BACKGROUND = 1<<16;
93 
94     /* A layout was requested on this widget */
95     static const int LAYOUT_NEEDED  = 1<<17;
96 
97     /* The preferred size of a child has changed */
98     static const int LAYOUT_CHANGED = 1<<18;
99 
100     /* A layout was requested in this widget hierachy */
101     static const int LAYOUT_CHILD = 1<<19;
102 
103     /* More global state flags */
104     static const int RELEASED = 1<<20;
105     static const int DISPOSE_SENT = 1<<21;
106     static const int FOREIGN_HANDLE = 1<<22;
107     static const int DRAG_DETECT = 1<<23;
108 
109     /* Default size for widgets */
110     static const int DEFAULT_WIDTH  = 64;
111     static const int DEFAULT_HEIGHT = 64;
112 
113     /* GTK signals data */
114     static const int ACTIVATE = 1;
115     static const int BUTTON_PRESS_EVENT = 2;
116     static const int BUTTON_PRESS_EVENT_INVERSE = 3;
117     static const int BUTTON_RELEASE_EVENT = 4;
118     static const int BUTTON_RELEASE_EVENT_INVERSE = 5;
119     static const int CHANGED = 6;
120     static const int CHANGE_VALUE = 7;
121     static const int CLICKED = 8;
122     static const int COMMIT = 9;
123     static const int CONFIGURE_EVENT = 10;
124     static const int DELETE_EVENT = 11;
125     static const int DELETE_RANGE = 12;
126     static const int DELETE_TEXT = 13;
127     static const int ENTER_NOTIFY_EVENT = 14;
128     static const int EVENT = 15;
129     static const int EVENT_AFTER = 16;
130     static const int EXPAND_COLLAPSE_CURSOR_ROW = 17;
131     static const int EXPOSE_EVENT = 18;
132     static const int EXPOSE_EVENT_INVERSE = 19;
133     static const int FOCUS = 20;
134     static const int FOCUS_IN_EVENT = 21;
135     static const int FOCUS_OUT_EVENT = 22;
136     static const int GRAB_FOCUS = 23;
137     static const int HIDE = 24;
138     static const int INPUT = 25;
139     static const int INSERT_TEXT = 26;
140     static const int KEY_PRESS_EVENT = 27;
141     static const int KEY_RELEASE_EVENT = 28;
142     static const int LEAVE_NOTIFY_EVENT = 29;
143     static const int MAP = 30;
144     static const int MAP_EVENT = 31;
145     static const int MNEMONIC_ACTIVATE = 32;
146     static const int MOTION_NOTIFY_EVENT = 33;
147     static const int MOTION_NOTIFY_EVENT_INVERSE = 34;
148     static const int MOVE_FOCUS = 35;
149     static const int OUTPUT = 36;
150     static const int POPULATE_POPUP = 37;
151     static const int POPUP_MENU = 38;
152     static const int PREEDIT_CHANGED = 39;
153     static const int REALIZE = 40;
154     static const int ROW_ACTIVATED = 41;
155     static const int SCROLL_CHILD = 42;
156     static const int SCROLL_EVENT = 43;
157     static const int SELECT = 44;
158     static const int SHOW = 45;
159     static const int SHOW_HELP = 46;
160     static const int SIZE_ALLOCATE = 47;
161     static const int STYLE_SET = 48;
162     static const int SWITCH_PAGE = 49;
163     static const int TEST_COLLAPSE_ROW = 50;
164     static const int TEST_EXPAND_ROW = 51;
165     static const int TEXT_BUFFER_INSERT_TEXT = 52;
166     static const int TOGGLED = 53;
167     static const int UNMAP = 54;
168     static const int UNMAP_EVENT = 55;
169     static const int UNREALIZE = 56;
170     static const int VALUE_CHANGED = 57;
171     static const int VISIBILITY_NOTIFY_EVENT = 58;
172     static const int WINDOW_STATE_EVENT = 59;
173     static const int ACTIVATE_INVERSE = 60;
174     static const int DAY_SELECTED = 61;
175     static const int MONTH_CHANGED = 62;
176     static const int LAST_SIGNAL = 63;
177 
178     static String UD_Getter(String name) (){
179         return "void* ud"~name~"(){ return getDisplay().getWindowProcUserData( "~name~"); }\n";
180     }
181 
182     mixin ( UD_Getter!( "ACTIVATE" )() );
183     mixin ( UD_Getter!( "BUTTON_PRESS_EVENT" )() );
184     mixin ( UD_Getter!( "BUTTON_PRESS_EVENT_INVERSE" )() );
185     mixin ( UD_Getter!( "BUTTON_RELEASE_EVENT" )() );
186     mixin ( UD_Getter!( "BUTTON_RELEASE_EVENT_INVERSE" )() );
187     mixin ( UD_Getter!( "CHANGED" )() );
188     mixin ( UD_Getter!( "CHANGE_VALUE" )() );
189     mixin ( UD_Getter!( "CLICKED" )() );
190     mixin ( UD_Getter!( "COMMIT" )() );
191     mixin ( UD_Getter!( "CONFIGURE_EVENT" )() );
192     mixin ( UD_Getter!( "DELETE_EVENT" )() );
193     mixin ( UD_Getter!( "DELETE_RANGE" )() );
194     mixin ( UD_Getter!( "DELETE_TEXT" )() );
195     mixin ( UD_Getter!( "ENTER_NOTIFY_EVENT" )() );
196     mixin ( UD_Getter!( "EVENT" )() );
197     mixin ( UD_Getter!( "EVENT_AFTER" )() );
198     mixin ( UD_Getter!( "EXPAND_COLLAPSE_CURSOR_ROW" )() );
199     mixin ( UD_Getter!( "EXPOSE_EVENT" )() );
200     mixin ( UD_Getter!( "EXPOSE_EVENT_INVERSE" )() );
201     mixin ( UD_Getter!( "FOCUS" )() );
202     mixin ( UD_Getter!( "FOCUS_IN_EVENT" )() );
203     mixin ( UD_Getter!( "FOCUS_OUT_EVENT" )() );
204     mixin ( UD_Getter!( "GRAB_FOCUS" )() );
205     mixin ( UD_Getter!( "HIDE" )() );
206     mixin ( UD_Getter!( "INPUT" )() );
207     mixin ( UD_Getter!( "INSERT_TEXT" )() );
208     mixin ( UD_Getter!( "KEY_PRESS_EVENT" )() );
209     mixin ( UD_Getter!( "KEY_RELEASE_EVENT" )() );
210     mixin ( UD_Getter!( "LEAVE_NOTIFY_EVENT" )() );
211     mixin ( UD_Getter!( "MAP" )() );
212     mixin ( UD_Getter!( "MAP_EVENT" )() );
213     mixin ( UD_Getter!( "MNEMONIC_ACTIVATE" )() );
214     mixin ( UD_Getter!( "MOTION_NOTIFY_EVENT" )() );
215     mixin ( UD_Getter!( "MOTION_NOTIFY_EVENT_INVERSE" )() );
216     mixin ( UD_Getter!( "MOVE_FOCUS" )() );
217     mixin ( UD_Getter!( "OUTPUT" )() );
218     mixin ( UD_Getter!( "POPULATE_POPUP" )() );
219     mixin ( UD_Getter!( "POPUP_MENU" )() );
220     mixin ( UD_Getter!( "PREEDIT_CHANGED" )() );
221     mixin ( UD_Getter!( "REALIZE" )() );
222     mixin ( UD_Getter!( "ROW_ACTIVATED" )() );
223     mixin ( UD_Getter!( "SCROLL_CHILD" )() );
224     mixin ( UD_Getter!( "SCROLL_EVENT" )() );
225     mixin ( UD_Getter!( "SELECT" )() );
226     mixin ( UD_Getter!( "SHOW" )() );
227     mixin ( UD_Getter!( "SHOW_HELP" )() );
228     mixin ( UD_Getter!( "SIZE_ALLOCATE" )() );
229     mixin ( UD_Getter!( "STYLE_SET" )() );
230     mixin ( UD_Getter!( "SWITCH_PAGE" )() );
231     mixin ( UD_Getter!( "TEST_COLLAPSE_ROW" )() );
232     mixin ( UD_Getter!( "TEST_EXPAND_ROW" )() );
233     mixin ( UD_Getter!( "TEXT_BUFFER_INSERT_TEXT" )() );
234     mixin ( UD_Getter!( "TOGGLED" )() );
235     mixin ( UD_Getter!( "UNMAP" )() );
236     mixin ( UD_Getter!( "UNMAP_EVENT" )() );
237     mixin ( UD_Getter!( "UNREALIZE" )() );
238     mixin ( UD_Getter!( "VALUE_CHANGED" )() );
239     mixin ( UD_Getter!( "VISIBILITY_NOTIFY_EVENT" )() );
240     mixin ( UD_Getter!( "WINDOW_STATE_EVENT" )() );
241     mixin ( UD_Getter!( "ACTIVATE_INVERSE" )() );
242     mixin ( UD_Getter!( "DAY_SELECTED" )() );
243     mixin ( UD_Getter!( "MONTH_CHANGED" )() );
244     mixin ( UD_Getter!( "LAST_SIGNAL" )() );
245 
246 /**
247  * Prevents uninitialized instances from being created outside the package.
248  */
249 this () {}
250 
251 /**
252  * Constructs a new instance of this class given its parent
253  * and a style value describing its behavior and appearance.
254  * <p>
255  * The style value is either one of the style constants defined in
256  * class <code>SWT</code> which is applicable to instances of this
257  * class, or must be built by <em>bitwise OR</em>'ing together
258  * (that is, using the <code>int</code> "|" operator) two or more
259  * of those <code>SWT</code> style constants. The class description
260  * lists the style constants that are applicable to the class.
261  * Style bits are also inherited from superclasses.
262  * </p>
263  *
264  * @param parent a widget which will be the parent of the new instance (cannot be null)
265  * @param style the style of widget to construct
266  *
267  * @exception IllegalArgumentException <ul>
268  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
269  *    <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li>
270  * </ul>
271  * @exception SWTException <ul>
272  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
273  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
274  * </ul>
275  *
276  * @see SWT
277  * @see #checkSubclass
278  * @see #getStyle
279  */
280 public this (Widget parent, int style) {
281     checkSubclass ();
282     checkParent (parent);
283     this.style = style;
284     display = parent.display;
285 }
286 
287 void _addListener (int eventType, Listener listener) {
288     if (eventTable is null) eventTable = new EventTable ();
289     eventTable.hook (eventType, listener);
290 }
291 
292 /**
293  * Adds the listener to the collection of listeners who will
294  * be notified when an event of the given type occurs. When the
295  * event does occur in the widget, the listener is notified by
296  * sending it the <code>handleEvent()</code> message. The event
297  * type is one of the event constants defined in class <code>SWT</code>.
298  *
299  * @param eventType the type of event to listen for
300  * @param listener the listener which should be notified when the event occurs
301  *
302  * @exception IllegalArgumentException <ul>
303  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
304  * </ul>
305  * @exception SWTException <ul>
306  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
307  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
308  * </ul>
309  *
310  * @see Listener
311  * @see SWT
312  * @see #getListeners(int)
313  * @see #removeListener(int, Listener)
314  * @see #notifyListeners
315  */
316 public void addListener (int eventType, Listener listener) {
317     checkWidget ();
318     if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
319     _addListener (eventType, listener);
320 }
321 
322 /**
323  * Adds the listener to the collection of listeners who will
324  * be notified when the widget is disposed. When the widget is
325  * disposed, the listener is notified by sending it the
326  * <code>widgetDisposed()</code> message.
327  *
328  * @param listener the listener which should be notified when the receiver is disposed
329  *
330  * @exception IllegalArgumentException <ul>
331  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
332  * </ul>
333  * @exception SWTException <ul>
334  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
335  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
336  * </ul>
337  *
338  * @see DisposeListener
339  * @see #removeDisposeListener
340  */
341 public void addDisposeListener (DisposeListener listener) {
342     checkWidget ();
343     if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
344     TypedListener typedListener = new TypedListener (listener);
345     addListener (SWT.Dispose, typedListener);
346 }
347 
348 GdkWindow* paintWindow () {
349     return null;
350 }
351 
352 static int checkBits (int style, int int0, int int1, int int2, int int3, int int4, int int5) {
353     int mask = int0 | int1 | int2 | int3 | int4 | int5;
354     if ((style & mask) is 0) style |= int0;
355     if ((style & int0) !is 0) style = (style & ~mask) | int0;
356     if ((style & int1) !is 0) style = (style & ~mask) | int1;
357     if ((style & int2) !is 0) style = (style & ~mask) | int2;
358     if ((style & int3) !is 0) style = (style & ~mask) | int3;
359     if ((style & int4) !is 0) style = (style & ~mask) | int4;
360     if ((style & int5) !is 0) style = (style & ~mask) | int5;
361     return style;
362 }
363 
364 void cellDataProc (
365     GtkTreeViewColumn *tree_column,
366     GtkCellRenderer *cell,
367     GtkTreeModel *tree_model,
368     GtkTreeIter *iter,
369     void* data)
370 {
371 }
372 
373 void checkOpen () {
374     /* Do nothing */
375 }
376 
377 void checkOrientation (Widget parent) {
378     style &= ~SWT.MIRRORED;
379     if ((style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT)) is 0) {
380         if (parent !is null) {
381             if ((parent.style & SWT.LEFT_TO_RIGHT) !is 0) style |= SWT.LEFT_TO_RIGHT;
382             if ((parent.style & SWT.RIGHT_TO_LEFT) !is 0) style |= SWT.RIGHT_TO_LEFT;
383         }
384     }
385     style = checkBits (style, SWT.LEFT_TO_RIGHT, SWT.RIGHT_TO_LEFT, 0, 0, 0, 0);
386     /* Versions of GTK prior to 2.8 do not render RTL text properly */
387     if (OS.GTK_VERSION < OS.buildVERSION (2, 8, 0)) {
388         style &= ~SWT.RIGHT_TO_LEFT;
389         style |= SWT.LEFT_TO_RIGHT;
390     }
391 }
392 
393 /**
394  * Throws an exception if the specified widget can not be
395  * used as a parent for the receiver.
396  *
397  * @exception IllegalArgumentException <ul>
398  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
399  *    <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li>
400  * </ul>
401  * @exception SWTException <ul>
402  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
403  * </ul>
404  */
405 void checkParent (Widget parent) {
406     if (parent is null) error (SWT.ERROR_NULL_ARGUMENT);
407     if (parent.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
408     parent.checkWidget ();
409     parent.checkOpen ();
410 }
411 
412 /**
413  * Checks that this class can be subclassed.
414  * <p>
415  * The SWT class library is intended to be subclassed
416  * only at specific, controlled points (most notably,
417  * <code>Composite</code> and <code>Canvas</code> when
418  * implementing new widgets). This method enforces this
419  * rule unless it is overridden.
420  * </p><p>
421  * <em>IMPORTANT:</em> By providing an implementation of this
422  * method that allows a subclass of a class which does not
423  * normally allow subclassing to be created, the implementer
424  * agrees to be fully responsible for the fact that any such
425  * subclass will likely fail between SWT releases and will be
426  * strongly platform specific. No support is provided for
427  * user-written classes which are implemented in this fashion.
428  * </p><p>
429  * The ability to subclass outside of the allowed SWT classes
430  * is intended purely to enable those not on the SWT development
431  * team to implement patches in order to get around specific
432  * limitations in advance of when those limitations can be
433  * addressed by the team. Subclassing should not be attempted
434  * without an intimate and detailed understanding of the hierarchy.
435  * </p>
436  *
437  * @exception SWTException <ul>
438  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
439  * </ul>
440  */
441 protected void checkSubclass () {
442     if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
443 }
444 
445 /**
446  * Throws an <code>SWTException</code> if the receiver can not
447  * be accessed by the caller. This may include both checks on
448  * the state of the receiver and more generally on the entire
449  * execution context. This method <em>should</em> be called by
450  * widget implementors to enforce the standard SWT invariants.
451  * <p>
452  * Currently, it is an error to invoke any method (other than
453  * <code>isDisposed()</code>) on a widget that has had its
454  * <code>dispose()</code> method called. It is also an error
455  * to call widget methods from any thread that is different
456  * from the thread that created the widget.
457  * </p><p>
458  * In future releases of SWT, there may be more or fewer error
459  * checks and exceptions may be thrown for different reasons.
460  * </p>
461  *
462  * @exception SWTException <ul>
463  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
464  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
465  * </ul>
466  */
467 public void checkWidget () {
468     Display display = this.display;
469     if (display is null) error (SWT.ERROR_WIDGET_DISPOSED);
470     if (display.thread !is Thread.currentThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
471     if ((state & DISPOSED) !is 0) error (SWT.ERROR_WIDGET_DISPOSED);
472 }
473 
474 void createHandle (int index) {
475 }
476 
477 void createWidget (int index) {
478     createHandle (index);
479     setOrientation ();
480     hookEvents ();
481     register ();
482 }
483 
484 void deregister () {
485     if (handle is null) return;
486     if ((state & HANDLE) !is 0) display.removeWidget (handle);
487 }
488 
489 void destroyWidget () {
490     GtkWidget* h = topHandle ();
491     releaseHandle ();
492     if (h !is null && (state & HANDLE) !is 0) {
493         OS.gtk_widget_destroy (h);
494     }
495 }
496 
497 /**
498  * Disposes of the operating system resources associated with
499  * the receiver and all its descendants. After this method has
500  * been invoked, the receiver and all descendants will answer
501  * <code>true</code> when sent the message <code>isDisposed()</code>.
502  * Any internal connections between the widgets in the tree will
503  * have been removed to facilitate garbage collection.
504  * <p>
505  * NOTE: This method is not called recursively on the descendants
506  * of the receiver. This means that, widget implementers can not
507  * detect when a widget is being disposed of by re-implementing
508  * this method, but should instead listen for the <code>Dispose</code>
509  * event.
510  * </p>
511  *
512  * @exception SWTException <ul>
513  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
514  * </ul>
515  *
516  * @see #addDisposeListener
517  * @see #removeDisposeListener
518  * @see #checkWidget
519  */
520 public void dispose () {
521     /*
522     * Note:  It is valid to attempt to dispose a widget
523     * more than once.  If this happens, fail silently.
524     */
525     if (isDisposed ()) return;
526     if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
527     release (true);
528 }
529 
530 void error (int code) {
531     SWT.error (code);
532 }
533 
534 /**
535  * Returns the application defined widget data associated
536  * with the receiver, or null if it has not been set. The
537  * <em>widget data</em> is a single, unnamed field that is
538  * stored with every widget.
539  * <p>
540  * Applications may put arbitrary objects in this field. If
541  * the object stored in the widget data needs to be notified
542  * when the widget is disposed of, it is the application's
543  * responsibility to hook the Dispose event on the widget and
544  * do so.
545  * </p>
546  *
547  * @return the widget data
548  *
549  * @exception SWTException <ul>
550  *    <li>ERROR_WIDGET_DISPOSED - when the receiver has been disposed</li>
551  *    <li>ERROR_THREAD_INVALID_ACCESS - when called from the wrong thread</li>
552  * </ul>
553  *
554  * @see #setData(Object)
555  */
556 public Object getData () {
557     checkWidget();
558     return (state & KEYED_DATA) !is 0 ? (cast(ArrayWrapperObject)data).array[0] : data;
559 }
560 public String getDataStr () {
561     return stringcast( getData() );
562 }
563 
564 /**
565  * Returns the application defined property of the receiver
566  * with the specified name, or null if it has not been set.
567  * <p>
568  * Applications may have associated arbitrary objects with the
569  * receiver in this fashion. If the objects stored in the
570  * properties need to be notified when the widget is disposed
571  * of, it is the application's responsibility to hook the
572  * Dispose event on the widget and do so.
573  * </p>
574  *
575  * @param   key the name of the property
576  * @return the value of the property or null if it has not been set
577  *
578  * @exception SWTException <ul>
579  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
580  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
581  * </ul>
582  *
583  * @see #setData(String, Object)
584  */
585 public Object getData (String key) {
586     checkWidget();
587     // SWT extension: allow null for zero length string
588     //if (key is null) error (SWT.ERROR_NULL_ARGUMENT);
589     if ((state & KEYED_DATA) !is 0) {
590         Object[] table = (cast(ArrayWrapperObject) data).array;
591         for (int i=1; i<table.length; i+=2) {
592             String tablekey = stringcast(table[i]);
593             if (key.equals( tablekey) ) return table [i+1];
594         }
595     }
596     return null;
597 }
598 public String getDataStr (String key) {
599     return stringcast( getData(key) );
600 }
601 
602 /**
603  * Returns the <code>Display</code> that is associated with
604  * the receiver.
605  * <p>
606  * A widget's display is either provided when it is created
607  * (for example, top level <code>Shell</code>s) or is the
608  * same as its parent's display.
609  * </p>
610  *
611  * @return the receiver's display
612  *
613  * @exception SWTException <ul>
614  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
615  * </ul>
616  */
617 public Display getDisplay () {
618     Display display = this.display;
619     if (display is null) error (SWT.ERROR_WIDGET_DISPOSED);
620     return display;
621 }
622 
623 /**
624  * Returns an array of listeners who will be notified when an event
625  * of the given type occurs. The event type is one of the event constants
626  * defined in class <code>SWT</code>.
627  *
628  * @param eventType the type of event to listen for
629  * @return an array of listeners that will be notified when the event occurs
630  *
631  * @exception SWTException <ul>
632  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
633  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
634  * </ul>
635  *
636  * @see Listener
637  * @see SWT
638  * @see #addListener(int, Listener)
639  * @see #removeListener(int, Listener)
640  * @see #notifyListeners
641  *
642  * @since 3.4
643  */
644 public Listener[] getListeners (int eventType) {
645     checkWidget();
646     if (eventTable is null) return new Listener[0];
647     return eventTable.getListeners(eventType);
648 }
649 
650 String getName () {
651 //  String str = getClass ().getName ();
652 //  int index = str.lastIndexOf ('.');
653 //  if (index is -1) return str;
654     String str = this.classinfo.name;
655     auto index = str.length;
656     while ((--index > 0) && (str[index] !is '.')) {}
657     return str[index + 1 .. $ ];
658 }
659 
660 String getNameText () {
661     return "";
662 }
663 
664 /**
665  * Returns the receiver's style information.
666  * <p>
667  * Note that the value which is returned by this method <em>may
668  * not match</em> the value which was provided to the constructor
669  * when the receiver was created. This can occur when the underlying
670  * operating system does not support a particular combination of
671  * requested styles. For example, if the platform widget used to
672  * implement a particular SWT widget always has scroll bars, the
673  * result of calling this method would always have the
674  * <code>SWT.H_SCROLL</code> and <code>SWT.V_SCROLL</code> bits set.
675  * </p>
676  *
677  * @return the style bits
678  *
679  * @exception SWTException <ul>
680  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
681  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
682  * </ul>
683  */
684 public int getStyle () {
685     checkWidget ();
686     return style;
687 }
688 
689 
690 int gtk_activate (GtkWidget* widget) {
691     return 0;
692 }
693 
694 int gtk_button_press_event (GtkWidget* widget, GdkEventButton* event) {
695     return 0;
696 }
697 
698 int gtk_button_release_event (GtkWidget* widget, GdkEventButton* event) {
699     return 0;
700 }
701 
702 int gtk_changed (GtkWidget* widget) {
703     return 0;
704 }
705 
706 int gtk_change_value (GtkWidget* widget, int scroll, double value1, void* user_data) {
707     return 0;
708 }
709 
710 int gtk_clicked (GtkWidget* widget) {
711     return 0;
712 }
713 
714 int gtk_commit (GtkIMContext* imcontext, char* text) {
715     return 0;
716 }
717 
718 int gtk_configure_event (GtkWidget* widget, ptrdiff_t event) {
719     return 0;
720 }
721 
722 int gtk_day_selected (GtkWidget* widget) {
723     return 0;
724 }
725 
726 int gtk_delete_event (GtkWidget* widget, ptrdiff_t event) {
727     return 0;
728 }
729 
730 int gtk_delete_range (GtkWidget* widget, ptrdiff_t iter1, ptrdiff_t iter2) {
731     return 0;
732 }
733 
734 int gtk_delete_text (GtkWidget* widget, ptrdiff_t start_pos, ptrdiff_t end_pos) {
735     return 0;
736 }
737 
738 int gtk_enter_notify_event (GtkWidget* widget, GdkEventCrossing* event) {
739     return 0;
740 }
741 
742 int gtk_event (GtkWidget* widget, GdkEvent* event) {
743     return 0;
744 }
745 
746 int gtk_event_after (GtkWidget* widget, GdkEvent* event) {
747     return 0;
748 }
749 
750 int gtk_expand_collapse_cursor_row (GtkWidget* widget, ptrdiff_t logical, ptrdiff_t expand, ptrdiff_t open_all) {
751     return 0;
752 }
753 
754 int gtk_expose_event (GtkWidget* widget, GdkEventExpose* event) {
755     return 0;
756 }
757 
758 int gtk_focus (GtkWidget* widget, ptrdiff_t directionType) {
759     return 0;
760 }
761 
762 int gtk_focus_in_event (GtkWidget* widget, GdkEventFocus* event) {
763     return 0;
764 }
765 
766 int gtk_focus_out_event (GtkWidget* widget, GdkEventFocus* event) {
767     return 0;
768 }
769 
770 int gtk_grab_focus (GtkWidget* widget) {
771     return 0;
772 }
773 
774 int gtk_hide (GtkWidget* widget) {
775     return 0;
776 }
777 
778 int gtk_input (GtkWidget* widget, ptrdiff_t arg1) {
779     return 0;
780 }
781 
782 int gtk_insert_text (GtkEditable* widget, char* new_text, ptrdiff_t new_text_length, ptrdiff_t position) {
783     return 0;
784 }
785 
786 int gtk_key_press_event (GtkWidget* widget, GdkEventKey* event) {
787     return sendKeyEvent (SWT.KeyDown, event) ? 0 : 1;
788 }
789 
790 int gtk_key_release_event (GtkWidget* widget, GdkEventKey* event) {
791     return sendKeyEvent (SWT.KeyUp, event) ? 0 : 1;
792 }
793 
794 int gtk_leave_notify_event (GtkWidget* widget, GdkEventCrossing* event) {
795     return 0;
796 }
797 
798 int gtk_map (GtkWidget* widget) {
799     return 0;
800 }
801 
802 int gtk_map_event (GtkWidget* widget, ptrdiff_t event) {
803     return 0;
804 }
805 
806 int gtk_mnemonic_activate (GtkWidget* widget, ptrdiff_t arg1) {
807     return 0;
808 }
809 
810 int gtk_month_changed (GtkWidget* widget) {
811     return 0;
812 }
813 
814 int gtk_motion_notify_event (GtkWidget* widget, GdkEventMotion* event) {
815     return 0;
816 }
817 
818 int gtk_move_focus (GtkWidget* widget, ptrdiff_t directionType) {
819     return 0;
820 }
821 
822 int gtk_output (GtkWidget* widget) {
823     return 0;
824 }
825 
826 int gtk_populate_popup (GtkWidget* widget, GtkWidget* menu) {
827     return 0;
828 }
829 
830 int gtk_popup_menu (GtkWidget* widget) {
831     return 0;
832 }
833 
834 int gtk_preedit_changed (GtkIMContext* imcontext) {
835     return 0;
836 }
837 
838 int gtk_realize (GtkWidget* widget) {
839     return 0;
840 }
841 
842 void gtk_row_activated (GtkTreeView* tree, GtkTreePath* path, GtkTreeViewColumn* column) {
843 }
844 
845 int gtk_scroll_child (GtkWidget* widget, ptrdiff_t scrollType, ptrdiff_t horizontal) {
846     return 0;
847 }
848 
849 int gtk_scroll_event (GtkWidget* widget, GdkEventScroll*  event) {
850     return 0;
851 }
852 
853 int gtk_select (int item) {
854     return 0;
855 }
856 
857 int gtk_show (GtkWidget* widget) {
858     return 0;
859 }
860 
861 int gtk_show_help (GtkWidget* widget, ptrdiff_t helpType) {
862     return 0;
863 }
864 
865 int gtk_size_allocate (GtkWidget* widget, ptrdiff_t allocation) {
866     return 0;
867 }
868 
869 int gtk_style_set (GtkWidget* widget, ptrdiff_t previousStyle) {
870     return 0;
871 }
872 
873 int gtk_switch_page (GtkWidget* widget, ptrdiff_t page, ptrdiff_t page_num) {
874     return 0;
875 }
876 
877 int gtk_test_collapse_row (
878     GtkTreeView *tree_view,
879     GtkTreeIter *iter,
880     GtkTreePath *path)
881 {
882     return 0;
883 }
884 
885 int gtk_test_expand_row (
886     GtkTreeView *tree_view,
887     GtkTreeIter *iter,
888     GtkTreePath *path)
889 {
890     return 0;
891 }
892 
893 int gtk_text_buffer_insert_text (GtkTextBuffer *buffer, GtkTextIter *iter, char *text, ptrdiff_t len) {
894     return 0;
895 }
896 
897 int gtk_timer () {
898     return 0;
899 }
900 
901 int gtk_toggled (int renderer, char* pathStr) {
902     return 0;
903 }
904 
905 int gtk_unmap (GtkWidget* widget) {
906     return 0;
907 }
908 
909 int gtk_unmap_event (GtkWidget* widget, ptrdiff_t event) {
910     return 0;
911 }
912 
913 int gtk_unrealize (GtkWidget* widget) {
914     return 0;
915 }
916 
917 int gtk_value_changed (int adjustment) {
918     return 0;
919 }
920 
921 int gtk_visibility_notify_event (GtkWidget* widget, GdkEventVisibility* event) {
922     return 0;
923 }
924 
925 int gtk_window_state_event (GtkWidget* widget, GdkEventWindowState* event) {
926     return 0;
927 }
928 
929 int fontHeight ( PangoFontDescription* font, GtkWidget* widgetHandle ) {
930     auto context = OS.gtk_widget_get_pango_context (widgetHandle);
931     auto lang = OS.pango_context_get_language (context);
932     auto metrics = OS.pango_context_get_metrics (context, font, lang);
933     int ascent = OS.pango_font_metrics_get_ascent (metrics);
934     int descent = OS.pango_font_metrics_get_descent (metrics);
935     OS.pango_font_metrics_unref (metrics);
936     return OS.PANGO_PIXELS (ascent + descent);
937 }
938 
939 int filterProc (XEvent* xEvent, GdkEvent* gdkEvent, void* data) {
940     return 0;
941 }
942 
943 bool filters (int eventType) {
944     return display.filters (eventType);
945 }
946 
947 int fixedMapProc (GtkWidget* widget) {
948     return 0;
949 }
950 
951 void fixedSizeAllocateProc(GtkWidget* widget, GtkAllocation* allocationPtr) {
952     return Display.oldFixedSizeAllocateProc(widget, allocationPtr);
953 }
954 
955 char [] fixMnemonic (String str) {
956     return fixMnemonic (str, true);
957 }
958 
959 char [] fixMnemonic (String str, bool replace) {
960     char[] text = str.dup;
961     int i = 0, j = 0;
962     char [] result = new char [str.length * 2];
963     while (i < str.length) {
964         switch (text [i]) {
965             case '&':
966                 if (i + 1 < str.length && text [i + 1] == '&') {
967                     result [j++] = text [i++];
968                 } else {
969                     if (replace) result [j++] = '_';
970                 }
971                 i++;
972                 break;
973             case '_':
974                 if (replace) result [j++] = '_';
975                 goto default;
976             default:
977                 result [j++] = text [i++];
978         }
979     }
980     if (j < result.length) result [j++] = 0;
981     return result[0 .. j];
982 }
983 
984 /**
985  * Returns <code>true</code> if the widget has been disposed,
986  * and <code>false</code> otherwise.
987  * <p>
988  * This method gets the dispose state for the widget.
989  * When a widget has been disposed, it is an error to
990  * invoke any other method using the widget.
991  * </p>
992  *
993  * @return <code>true</code> when the widget is disposed and <code>false</code> otherwise
994  */
995 public bool isDisposed () {
996     return (state & DISPOSED) !is 0;
997 }
998 
999 /**
1000  * Returns <code>true</code> if there are any listeners
1001  * for the specified event type associated with the receiver,
1002  * and <code>false</code> otherwise. The event type is one of
1003  * the event constants defined in class <code>SWT</code>.
1004  *
1005  * @param eventType the type of event
1006  * @return true if the event is hooked
1007  *
1008  * @exception SWTException <ul>
1009  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1010  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1011  * </ul>
1012  *
1013  * @see SWT
1014  */
1015 public bool isListening (int eventType) {
1016     checkWidget ();
1017     return hooks (eventType);
1018 }
1019 
1020 bool isValidThread () {
1021     return getDisplay ().isValidThread ();
1022 }
1023 
1024 bool isValidSubclass() {
1025     return true;//Display.isValidClass(getClass());
1026 }
1027 
1028 void hookEvents () {
1029 }
1030 
1031 /*
1032  * Returns <code>true</code> if the specified eventType is
1033  * hooked, and <code>false</code> otherwise. Implementations
1034  * of SWT can avoid creating objects and sending events
1035  * when an event happens in the operating system but
1036  * there are no listeners hooked for the event.
1037  *
1038  * @param eventType the event to be checked
1039  *
1040  * @return <code>true</code> when the eventType is hooked and <code>false</code> otherwise
1041  *
1042  * @see #isListening
1043  */
1044 bool hooks (int eventType) {
1045     if (eventTable is null) return false;
1046     return eventTable.hooks (eventType);
1047 }
1048 
1049 int hoverProc (GtkWidget* widget) {
1050     return 0;
1051 }
1052 
1053 void menuPositionProc (GtkMenu* menu, int* x, int* y, int* push_in, void* user_data) {
1054 }
1055 
1056 bool mnemonicHit (GtkWidget* mnemonicHandle, wchar key) {
1057     if (!mnemonicMatch (mnemonicHandle, key)) return false;
1058     OS.g_signal_handlers_block_matched ( cast(void*)mnemonicHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udMNEMONIC_ACTIVATE);
1059     bool result = cast(bool)OS.gtk_widget_mnemonic_activate (cast(GtkWidget*)mnemonicHandle, false);
1060     OS.g_signal_handlers_unblock_matched (cast(void*)mnemonicHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udMNEMONIC_ACTIVATE);
1061     return result;
1062 }
1063 
1064 bool mnemonicMatch (GtkWidget* mnemonicHandle, wchar key) {
1065     int keyval1 = OS.gdk_keyval_to_lower (OS.gdk_unicode_to_keyval (key));
1066     int keyval2 = OS.gdk_keyval_to_lower (OS.gtk_label_get_mnemonic_keyval (cast(GtkLabel*)mnemonicHandle));
1067     return keyval1 is keyval2;
1068 }
1069 
1070 void modifyStyle (GtkWidget* handle, GtkRcStyle* style) {
1071     OS.gtk_widget_modify_style (handle, style);
1072 }
1073 
1074 /**
1075  * Notifies all of the receiver's listeners for events
1076  * of the given type that one such event has occurred by
1077  * invoking their <code>handleEvent()</code> method.  The
1078  * event type is one of the event constants defined in class
1079  * <code>SWT</code>.
1080  *
1081  * @param eventType the type of event which has occurred
1082  * @param event the event data
1083  *
1084  * @exception SWTException <ul>
1085  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1086  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1087  * </ul>
1088  *
1089  * @see SWT
1090  * @see #addListener
1091  * @see #getListeners(int)
1092  * @see #removeListener(int, Listener)
1093  */
1094 public void notifyListeners (int eventType, Event event) {
1095     checkWidget();
1096     if (event is null) event = new Event ();
1097     sendEvent (eventType, event);
1098 }
1099 
1100 void postEvent (int eventType) {
1101     sendEvent (eventType, null, false);
1102 }
1103 
1104 void postEvent (int eventType, Event event) {
1105     sendEvent (eventType, event, false);
1106 }
1107 
1108 void register () {
1109     if (handle is null) return;
1110     if ((state & HANDLE) !is 0) display.addWidget (handle, this);
1111 }
1112 
1113 void release (bool destroy) {
1114     if ((state & DISPOSE_SENT) is 0) {
1115         state |= DISPOSE_SENT;
1116         sendEvent (SWT.Dispose);
1117     }
1118     if ((state & DISPOSED) is 0) {
1119         releaseChildren (destroy);
1120     }
1121     if ((state & RELEASED) is 0) {
1122         state |= RELEASED;
1123         if (destroy) {
1124             releaseParent ();
1125             releaseWidget ();
1126             destroyWidget ();
1127         } else {
1128             releaseWidget ();
1129             releaseHandle ();
1130         }
1131     }
1132 }
1133 
1134 void releaseChildren (bool destroy) {
1135 }
1136 
1137 void releaseHandle () {
1138     handle = null;
1139     state |= DISPOSED;
1140     display = null;
1141 }
1142 
1143 void releaseParent () {
1144     /* Do nothing */
1145 }
1146 
1147 void releaseWidget () {
1148     deregister ();
1149     eventTable = null;
1150     data = null;
1151 }
1152 
1153 /**
1154  * Removes the listener from the collection of listeners who will
1155  * be notified when an event of the given type occurs. The event
1156  * type is one of the event constants defined in class <code>SWT</code>.
1157  *
1158  * @param eventType the type of event to listen for
1159  * @param listener the listener which should no longer be notified
1160  *
1161  * @exception IllegalArgumentException <ul>
1162  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1163  * </ul>
1164  * @exception SWTException <ul>
1165  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1166  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1167  * </ul>
1168  *
1169  * @see Listener
1170  * @see SWT
1171  * @see #addListener
1172  * @see #getListeners(int)
1173  * @see #notifyListeners
1174  */
1175 public void removeListener (int eventType, Listener handler) {
1176     checkWidget ();
1177     if (handler is null) error (SWT.ERROR_NULL_ARGUMENT);
1178     if (eventTable is null) return;
1179     eventTable.unhook (eventType, handler);
1180 }
1181 
1182 /**
1183  * Removes the listener from the collection of listeners who will
1184  * be notified when an event of the given type occurs.
1185  * <p>
1186  * <b>IMPORTANT:</b> This method is <em>not</em> part of the SWT
1187  * public API. It is marked public only so that it can be shared
1188  * within the packages provided by SWT. It should never be
1189  * referenced from application code.
1190  * </p>
1191  *
1192  * @param eventType the type of event to listen for
1193  * @param listener the listener which should no longer be notified
1194  *
1195  * @exception IllegalArgumentException <ul>
1196  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1197  * </ul>
1198  * @exception SWTException <ul>
1199  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1200  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1201  * </ul>
1202  *
1203  * @see Listener
1204  * @see #addListener
1205  */
1206 protected void removeListener (int eventType, SWTEventListener handler) {
1207     checkWidget ();
1208     if (handler is null) error (SWT.ERROR_NULL_ARGUMENT);
1209     if (eventTable is null) return;
1210     eventTable.unhook (eventType, handler);
1211 }
1212 
1213 void rendererGetSizeProc (
1214     GtkCellRenderer      *cell,
1215     GtkWidget            *widget,
1216     GdkRectangle         *cell_area,
1217     int                  *x_offset,
1218     int                  *y_offset,
1219     int                  *width,
1220     int                  *height)
1221 {
1222 }
1223 
1224 void rendererRenderProc (
1225     GtkCellRenderer * cell,
1226     GdkDrawable * window,
1227     GtkWidget * widget,
1228     GdkRectangle *background_area,
1229     GdkRectangle *cell_area,
1230     GdkRectangle *expose_area,
1231     int flags)
1232 {
1233 }
1234 
1235 /**
1236  * Removes the listener from the collection of listeners who will
1237  * be notified when the widget is disposed.
1238  *
1239  * @param listener the listener which should no longer be notified
1240  *
1241  * @exception IllegalArgumentException <ul>
1242  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1243  * </ul>
1244  * @exception SWTException <ul>
1245  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1246  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1247  * </ul>
1248  *
1249  * @see DisposeListener
1250  * @see #addDisposeListener
1251  */
1252 public void removeDisposeListener (DisposeListener listener) {
1253     checkWidget ();
1254     if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
1255     if (eventTable is null) return;
1256     eventTable.unhook (SWT.Dispose, listener);
1257 }
1258 
1259 
1260 void sendEvent (Event event) {
1261     Display display = event.display;
1262     if (!display.filterEvent (event)) {
1263         if (eventTable !is null) eventTable.sendEvent (event);
1264     }
1265 }
1266 
1267 void sendEvent (int eventType) {
1268     sendEvent (eventType, null, true);
1269 }
1270 
1271 void sendEvent (int eventType, Event event) {
1272     sendEvent (eventType, event, true);
1273 }
1274 
1275 void sendEvent (int eventType, Event event, bool send) {
1276     if (eventTable is null && !display.filters (eventType)) {
1277         return;
1278     }
1279     if (event is null) event = new Event ();
1280     event.type = eventType;
1281     event.display = display;
1282     event.widget = this;
1283     if (event.time is 0) {
1284         event.time = display.getLastEventTime ();
1285     }
1286     if (send) {
1287         sendEvent (event);
1288     } else {
1289         display.postEvent (event);
1290     }
1291 }
1292 
1293 bool sendKeyEvent (int type, GdkEventKey* keyEvent) {
1294     size_t len = keyEvent.length;
1295     if (keyEvent..string is null || OS.g_utf8_strlen (keyEvent..string, len) <= 1) {
1296         Event event = new Event ();
1297         event.time = keyEvent.time;
1298         if (!setKeyState (event, keyEvent)) return true;
1299         sendEvent (type, event);
1300         // widget could be disposed at this point
1301 
1302         /*
1303         * It is possible (but unlikely), that application
1304         * code could have disposed the widget in the key
1305         * events.  If this happens, end the processing of
1306         * the key by returning false.
1307         */
1308         if (isDisposed ()) return false;
1309         return event.doit;
1310     }
1311     char [] chars = fromStringz( keyEvent..string );
1312     return sendIMKeyEvent (type, keyEvent, chars) !is null;
1313 }
1314 
1315 char [] sendIMKeyEvent (int type, GdkEventKey* keyEvent, char [] chars) {
1316     int index = 0, count = 0, state = 0;
1317     GdkEvent*  ptr = null;
1318     if (keyEvent is null) {
1319         ptr = OS.gtk_get_current_event ();
1320         if (ptr !is null) {
1321             keyEvent = cast(GdkEventKey*)ptr;
1322             switch (keyEvent.type) {
1323                 case OS.GDK_KEY_PRESS:
1324                 case OS.GDK_KEY_RELEASE:
1325                     state = keyEvent.state;
1326                     break;
1327                 default:
1328                     keyEvent = null;
1329                     break;
1330             }
1331         }
1332     }
1333     if (keyEvent is null) {
1334         int buffer;
1335         OS.gtk_get_current_event_state (&buffer);
1336         state = buffer;
1337     }
1338     while (index < chars.length) {
1339         Event event = new Event ();
1340         //PORTING take care of utf8
1341         if (keyEvent !is null && chars.UCScount() <= 1) {
1342             setKeyState (event, keyEvent);
1343         } else {
1344             setInputState (event, state);
1345         }
1346         //PORTING take care of utf8
1347         ptrdiff_t incr;
1348         event.character = cast(wchar) chars.dcharAt(index, incr);
1349         sendEvent (type, event);
1350 
1351         /*
1352         * It is possible (but unlikely), that application
1353         * code could have disposed the widget in the key
1354         * events.  If this happens, end the processing of
1355         * the key by returning null.
1356         */
1357         if (isDisposed ()) {
1358             if (ptr !is null) OS.gdk_event_free (ptr);
1359             return null;
1360         }
1361 
1362         //PORTING take care of utf8
1363         if (event.doit) {
1364             for( int i = 0; i < incr; i++ ){
1365                 chars [count+i] = chars [index+i];
1366             }
1367             count+=incr;
1368         }
1369         index+=incr;
1370     }
1371     if (ptr !is null) OS.gdk_event_free (ptr);
1372     if (count is 0) return null;
1373     if (index !is count) {
1374         char [] result = new char [count];
1375         System.arraycopy (chars, 0, result, 0, count);
1376         return result;
1377     }
1378     return chars;
1379 }
1380 
1381 /**
1382  * Sets the application defined widget data associated
1383  * with the receiver to be the argument. The <em>widget
1384  * data</em> is a single, unnamed field that is stored
1385  * with every widget.
1386  * <p>
1387  * Applications may put arbitrary objects in this field. If
1388  * the object stored in the widget data needs to be notified
1389  * when the widget is disposed of, it is the application's
1390  * responsibility to hook the Dispose event on the widget and
1391  * do so.
1392  * </p>
1393  *
1394  * @param data the widget data
1395  *
1396  * @exception SWTException <ul>
1397  *    <li>ERROR_WIDGET_DISPOSED - when the receiver has been disposed</li>
1398  *    <li>ERROR_THREAD_INVALID_ACCESS - when called from the wrong thread</li>
1399  * </ul>
1400  *
1401  * @see #getData()
1402  */
1403 public void setData (Object data) {
1404     checkWidget();
1405     if ((state & KEYED_DATA) !is 0) {
1406         (cast(ArrayWrapperObject) this.data).array[0] = data;
1407     } else {
1408         this.data = data;
1409     }
1410 }
1411 public void setDataStr (String data) {
1412     setData( stringcast(data));
1413 }
1414 
1415 /**
1416  * Sets the application defined property of the receiver
1417  * with the specified name to the given value.
1418  * <p>
1419  * Applications may associate arbitrary objects with the
1420  * receiver in this fashion. If the objects stored in the
1421  * properties need to be notified when the widget is disposed
1422  * of, it is the application's responsibility to hook the
1423  * Dispose event on the widget and do so.
1424  * </p>
1425  *
1426  * @param key the name of the property
1427  * @param value the new value for the property
1428  *
1429  * @exception SWTException <ul>
1430  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1431  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1432  * </ul>
1433  *
1434  * @see #getData(String)
1435  */
1436 public void setData (String key, Object value) {
1437     checkWidget();
1438     // SWT extension: allow null for zero length string
1439     //if (key is null) error (SWT.ERROR_NULL_ARGUMENT);
1440     int index = 1;
1441     Object [] table = null;
1442     if ((state & KEYED_DATA) !is 0) {
1443         table = (cast(ArrayWrapperObject) data).array;
1444         while (index < table.length) {
1445             String tablekey = stringcast(table[index]);
1446             if (key.equals (tablekey) ) break;
1447             index += 2;
1448         }
1449     }
1450     if (value !is null) {
1451         if ((state & KEYED_DATA) !is 0) {
1452             if (index is table.length) {
1453                 Object [] newTable = new Object [table.length + 2];
1454                 System.arraycopy (table, 0, newTable, 0, table.length);
1455                 table = newTable;
1456                 data = new ArrayWrapperObject( table );
1457             }
1458         } else {
1459             table = new Object [3];
1460             table [0] = data;
1461             data = new ArrayWrapperObject( table );
1462             state |= KEYED_DATA;
1463         }
1464         table [index] = new ArrayWrapperString( key );
1465         table [index + 1] = value;
1466     } else {
1467         if ((state & KEYED_DATA) !is 0) {
1468             if (index !is table.length) {
1469                 ptrdiff_t len = table.length - 2;
1470                 if (len is 1) {
1471                     data = table [0];
1472                     state &= ~KEYED_DATA;
1473                 } else {
1474                     Object [] newTable = new Object [len];
1475                     System.arraycopy (table, 0, newTable, 0, index);
1476                     System.arraycopy (table, index + 2, newTable, index, len - index);
1477                     data = new ArrayWrapperObject( newTable );
1478                 }
1479             }
1480         }
1481     }
1482 }
1483 public void setDataStr (String key, String value) {
1484     setData(key, stringcast(value));
1485 }
1486 
1487 void setForegroundColor (GtkWidget* handle, GdkColor* color) {
1488     auto style = OS.gtk_widget_get_modifier_style (handle);
1489     OS.gtk_rc_style_set_fg (style, OS.GTK_STATE_NORMAL, color);
1490     OS.gtk_rc_style_set_fg (style, OS.GTK_STATE_ACTIVE, color);
1491     OS.gtk_rc_style_set_fg (style, OS.GTK_STATE_PRELIGHT, color);
1492     int flags = OS.gtk_rc_style_get_color_flags (style, OS.GTK_STATE_NORMAL);
1493     flags = (color is null) ? flags & ~OS.GTK_RC_FG: flags | OS.GTK_RC_FG;
1494     OS.gtk_rc_style_set_color_flags (style, OS.GTK_STATE_NORMAL, flags);
1495     flags = OS.gtk_rc_style_get_color_flags (style, OS.GTK_STATE_ACTIVE);
1496     flags = (color is null) ? flags & ~OS.GTK_RC_FG: flags | OS.GTK_RC_FG;
1497     OS.gtk_rc_style_set_color_flags (style, OS.GTK_STATE_ACTIVE, flags);
1498     flags = OS.gtk_rc_style_get_color_flags (style, OS.GTK_STATE_PRELIGHT);
1499     flags = (color is null) ? flags & ~OS.GTK_RC_FG: flags | OS.GTK_RC_FG;
1500     OS.gtk_rc_style_set_color_flags (style, OS.GTK_STATE_PRELIGHT, flags);
1501 
1502     OS.gtk_rc_style_set_text (style, OS.GTK_STATE_NORMAL, color);
1503     OS.gtk_rc_style_set_text (style, OS.GTK_STATE_ACTIVE, color);
1504     OS.gtk_rc_style_set_text (style, OS.GTK_STATE_PRELIGHT, color);
1505     flags = OS.gtk_rc_style_get_color_flags (style, OS.GTK_STATE_NORMAL);
1506     flags = (color is null) ? flags & ~OS.GTK_RC_TEXT: flags | OS.GTK_RC_TEXT;
1507     OS.gtk_rc_style_set_color_flags (style, OS.GTK_STATE_NORMAL, flags);
1508     flags = OS.gtk_rc_style_get_color_flags (style, OS.GTK_STATE_PRELIGHT);
1509     flags = (color is null) ? flags & ~OS.GTK_RC_TEXT: flags | OS.GTK_RC_TEXT;
1510     OS.gtk_rc_style_set_color_flags (style, OS.GTK_STATE_PRELIGHT, flags);
1511     flags = OS.gtk_rc_style_get_color_flags (style, OS.GTK_STATE_ACTIVE);
1512     flags = (color is null) ? flags & ~OS.GTK_RC_TEXT: flags | OS.GTK_RC_TEXT;
1513     OS.gtk_rc_style_set_color_flags (style, OS.GTK_STATE_ACTIVE, flags);
1514     modifyStyle (handle, style);
1515 }
1516 
1517 bool setInputState (Event event, int state) {
1518     if ((state & OS.GDK_MOD1_MASK) !is 0) event.stateMask |= SWT.ALT;
1519     if ((state & OS.GDK_SHIFT_MASK) !is 0) event.stateMask |= SWT.SHIFT;
1520     if ((state & OS.GDK_CONTROL_MASK) !is 0) event.stateMask |= SWT.CONTROL;
1521     if ((state & OS.GDK_BUTTON1_MASK) !is 0) event.stateMask |= SWT.BUTTON1;
1522     if ((state & OS.GDK_BUTTON2_MASK) !is 0) event.stateMask |= SWT.BUTTON2;
1523     if ((state & OS.GDK_BUTTON3_MASK) !is 0) event.stateMask |= SWT.BUTTON3;
1524     return true;
1525 }
1526 
1527 bool setKeyState (Event event, GdkEventKey* keyEvent) {
1528     if (keyEvent..string !is null && OS.g_utf8_strlen (keyEvent..string, keyEvent.length) > 1) return false;
1529     bool isNull = false;
1530     event.keyCode = Display.translateKey (keyEvent.keyval);
1531     switch (keyEvent.keyval) {
1532         case OS.GDK_BackSpace:      event.character = SWT.BS; break;
1533         case OS.GDK_Linefeed:       event.character = SWT.LF; break;
1534         case OS.GDK_KP_Enter:
1535         case OS.GDK_Return:         event.character = SWT.CR; break;
1536         case OS.GDK_KP_Delete:
1537         case OS.GDK_Delete:         event.character = SWT.DEL; break;
1538         case OS.GDK_Escape:         event.character = SWT.ESC; break;
1539         case OS.GDK_Tab:
1540         case OS.GDK_ISO_Left_Tab:   event.character = SWT.TAB; break;
1541         default: {
1542             if (event.keyCode is 0) {
1543                 uint keyval;
1544                 int effective_group, level;
1545                 int consumed_modifiers;
1546                 if (OS.gdk_keymap_translate_keyboard_state(OS.gdk_keymap_get_default (), keyEvent.hardware_keycode, 0, keyEvent.group, &keyval, &effective_group, &level, &consumed_modifiers)) {
1547                     event.keyCode = OS.gdk_keyval_to_unicode (keyval );
1548                 }
1549             }
1550             int key = keyEvent.keyval;
1551             if ((keyEvent.state & OS.GDK_CONTROL_MASK) !is 0 && (0 <= key && key <= 0x7F)) {
1552                 if ('a'  <= key && key <= 'z') key -= 'a' - 'A';
1553                 if (64 <= key && key <= 95) key -= 64;
1554                 event.character = cast(char) key;
1555                 isNull = keyEvent.keyval is '@' && key is 0;
1556             } else {
1557                 event.character = cast(char) OS.gdk_keyval_to_unicode (key);
1558             }
1559         }
1560     }
1561     if (event.keyCode is 0 && event.character is 0) {
1562         if (!isNull) return false;
1563     }
1564     return setInputState (event, keyEvent.state);
1565 }
1566 
1567 void setOrientation () {
1568 }
1569 
1570 int shellMapProc (GtkWidget* handle, ptrdiff_t arg0, ptrdiff_t user_data) {
1571     return 0;
1572 }
1573 
1574 int sizeAllocateProc (GtkWidget* handle, ptrdiff_t arg0, ptrdiff_t user_data) {
1575     return 0;
1576 }
1577 
1578 int sizeRequestProc (GtkWidget* handle, ptrdiff_t arg0, ptrdiff_t user_data) {
1579     return 0;
1580 }
1581 
1582 /**
1583  * Returns a string containing a concise, human-readable
1584  * description of the receiver.
1585  *
1586  * @return a string representation of the receiver
1587  */
1588 public override String toString () {
1589     String str = "*Disposed*";
1590     if (!isDisposed ()) {
1591         str = "*Wrong Thread*";
1592         if (isValidThread ()) str = getNameText ();
1593     }
1594     return getName () ~ " {" ~ str ~ "}";
1595 }
1596 
1597 GtkWidget* topHandle () {
1598     return handle;
1599 }
1600 
1601 int timerProc (GtkWidget* widget) {
1602     return 0;
1603 }
1604 
1605 void treeSelectionProc (
1606     GtkTreeModel *model,
1607     GtkTreePath *path,
1608     GtkTreeIter *iter,
1609     int[] selection,
1610     int length)
1611 {
1612 }
1613 
1614 bool translateTraversal (int event) {
1615     return false;
1616 }
1617 
1618 int windowProc (GtkWidget* handle, ptrdiff_t user_data) {
1619     void trace( String str ){
1620         version(LOG) getDwtLogger().error( __FILE__, __LINE__,  "Widget windowProc {}", str ).flush;
1621     }
1622 
1623     switch (user_data) {
1624         case ACTIVATE:
1625             trace( "ACTIVATE" );
1626             return gtk_activate (handle);
1627         case CHANGED:
1628             trace( "CHANGED" );
1629             return gtk_changed (handle);
1630         case CLICKED:
1631             trace( "CLICKED" );
1632             return gtk_clicked (handle);
1633         case DAY_SELECTED:
1634             trace( "DAY_SELECTED" );
1635             return gtk_day_selected (handle);
1636         case HIDE:
1637             trace( "HIDE" );
1638             return gtk_hide (handle);
1639         case GRAB_FOCUS:
1640             trace( "GRAB_FOCUS" );
1641             return gtk_grab_focus (handle);
1642         case MAP:
1643             trace( "MAP" );
1644             return gtk_map (handle);
1645         case MONTH_CHANGED:
1646             trace( "MONTH_CHANGED" );
1647             return gtk_month_changed (handle);
1648         case OUTPUT:
1649             trace( "OUTPUT" );
1650             return gtk_output (handle);
1651         case POPUP_MENU:
1652             trace( "POPUP_MENU" );
1653             return gtk_popup_menu (handle);
1654         case PREEDIT_CHANGED:
1655             trace( "PREEDIT_CHANGED" );
1656             return gtk_preedit_changed (cast(GtkIMContext*)handle);
1657         case REALIZE:
1658             trace( "REALIZE" );
1659             return gtk_realize (handle);
1660         case SELECT:
1661             trace( "SELECT" );
1662             return gtk_select (cast(int)handle);
1663         case SHOW:
1664             trace( "SHOW" );
1665             return gtk_show (handle);
1666         case VALUE_CHANGED:
1667             trace( "VALUE_CHANGED" );
1668             return gtk_value_changed (cast(int)handle);
1669         case UNMAP:
1670             trace( "UNMAP" );
1671             return gtk_unmap (handle);
1672         case UNREALIZE:
1673             trace( "UNREALIZE" );
1674             return gtk_unrealize (handle);
1675         default:
1676             trace( "default" );
1677             return 0;
1678     }
1679 }
1680 
1681 int windowProc (GtkWidget* handle, ptrdiff_t arg0, ptrdiff_t user_data) {
1682     void trace( String str ){
1683         version(LOG) getDwtLogger().error( __FILE__, __LINE__,  "Widget windowProc1 {}", str ).flush;
1684     }
1685 
1686     switch (user_data) {
1687         case EXPOSE_EVENT_INVERSE: {
1688             trace( "EXPOSE_EVENT_INVERSE" );
1689             GdkEventExpose* gdkEvent = cast(GdkEventExpose*) arg0;
1690             auto paintWindow = paintWindow();
1691             auto window = gdkEvent.window;
1692             if (window !is paintWindow) return 0;
1693             return (state & OBSCURED) !is 0 ? 1 : 0;
1694         }
1695         case BUTTON_PRESS_EVENT_INVERSE:
1696         case BUTTON_RELEASE_EVENT_INVERSE:
1697         case MOTION_NOTIFY_EVENT_INVERSE: {
1698             trace( "BUTTON_PRESS_EVENT_INVERSE BUTTON_RELEASE_EVENT_INVERSE MOTION_NOTIFY_EVENT_INVERSE" );
1699             return 1;
1700         }
1701         case BUTTON_PRESS_EVENT:
1702             trace( "BUTTON_PRESS_EVENT" );
1703             return gtk_button_press_event (handle, cast(GdkEventButton*)arg0);
1704         case BUTTON_RELEASE_EVENT:
1705             trace( "BUTTON_RELEASE_EVENT" );
1706             return gtk_button_release_event (handle, cast(GdkEventButton*)arg0);
1707         case COMMIT:
1708             trace( "COMMIT" );
1709             return gtk_commit (cast(GtkIMContext*)handle, cast(char*)arg0);
1710         case CONFIGURE_EVENT:
1711             trace( "CONFIGURE_EVENT" );
1712             return gtk_configure_event (handle, arg0);
1713         case DELETE_EVENT:
1714             trace( "DELETE_EVENT" );
1715             return gtk_delete_event (handle, arg0);
1716         case ENTER_NOTIFY_EVENT:
1717             trace( "ENTER_NOTIFY_EVENT" );
1718             return gtk_enter_notify_event (handle, cast(GdkEventCrossing*)arg0);
1719         case EVENT:
1720             trace( "EVENT" );
1721             return gtk_event (handle, cast(GdkEvent*)arg0);
1722         case POPULATE_POPUP:
1723             trace( "POPULATE_POPUP" );
1724             return gtk_populate_popup (handle, cast(GtkWidget*)arg0);
1725         case EVENT_AFTER:
1726             trace( "EVENT_AFTER" );
1727             return gtk_event_after (handle, cast(GdkEvent*)arg0);
1728         case EXPOSE_EVENT:
1729             trace( "EXPOSE_EVENT" );
1730             return gtk_expose_event (handle, cast(GdkEventExpose*)arg0);
1731         case FOCUS:
1732             trace( "FOCUS" );
1733             return gtk_focus (handle, arg0);
1734         case FOCUS_IN_EVENT:
1735             trace( "FOCUS_IN_EVENT" );
1736             return gtk_focus_in_event (handle, cast(GdkEventFocus*)arg0);
1737         case FOCUS_OUT_EVENT:
1738             trace( "FOCUS_OUT_EVENT" );
1739             return gtk_focus_out_event (handle, cast(GdkEventFocus*)arg0);
1740         case KEY_PRESS_EVENT:
1741             trace( "KEY_PRESS_EVENT" );
1742             return gtk_key_press_event (handle, cast(GdkEventKey*)arg0);
1743         case KEY_RELEASE_EVENT:
1744             trace( "KEY_RELEASE_EVENT" );
1745             return gtk_key_release_event (handle, cast(GdkEventKey*)arg0);
1746         case INPUT:
1747             trace( "INPUT" );
1748             return gtk_input (handle, arg0);
1749         case LEAVE_NOTIFY_EVENT:
1750             trace( "LEAVE_NOTIFY_EVENT" );
1751             return gtk_leave_notify_event (handle, cast(GdkEventCrossing*)arg0);
1752         case MAP_EVENT:
1753             trace( "MAP_EVENT" );
1754             return gtk_map_event (handle, arg0);
1755         case MNEMONIC_ACTIVATE:
1756             trace( "MNEMONIC_ACTIVATE" );
1757             return gtk_mnemonic_activate (handle, arg0);
1758         case MOTION_NOTIFY_EVENT:
1759             trace( "MOTION_NOTIFY_EVENT" );
1760             return gtk_motion_notify_event (handle, cast(GdkEventMotion*)arg0);
1761         case MOVE_FOCUS:
1762             trace( "MOVE_FOCUS" );
1763             return gtk_move_focus (handle, arg0);
1764         case SCROLL_EVENT:
1765             trace( "SCROLL_EVENT" );
1766             return gtk_scroll_event (handle, cast(GdkEventScroll*)arg0);
1767         case SHOW_HELP:
1768             trace( "SHOW_HELP" );
1769             return gtk_show_help (handle, arg0);
1770         case SIZE_ALLOCATE:
1771             trace( "SIZE_ALLOCATE" );
1772             return gtk_size_allocate (handle, arg0);
1773         case STYLE_SET:
1774             trace( "STYLE_SET" );
1775             return gtk_style_set (handle, arg0);
1776         case TOGGLED:
1777             trace( "TOGGLED" );
1778             return gtk_toggled (cast(int)handle, cast(char*)arg0);
1779         case UNMAP_EVENT:
1780             trace( "UNMAP_EVENT" );
1781             return gtk_unmap_event (handle, arg0);
1782         case VISIBILITY_NOTIFY_EVENT:
1783             trace( "VISIBILITY_NOTIFY_EVENT" );
1784             return gtk_visibility_notify_event (handle, cast(GdkEventVisibility*)arg0);
1785         case WINDOW_STATE_EVENT:
1786             trace( "WINDOW_STATE_EVENT" );
1787             return gtk_window_state_event (handle, cast(GdkEventWindowState*)arg0);
1788         default:
1789             trace( "default" );
1790             return 0;
1791     }
1792 }
1793 
1794 int windowProc (GtkWidget* handle, ptrdiff_t arg0, ptrdiff_t arg1, ptrdiff_t user_data) {
1795     void trace( String str ){
1796         version(LOG) getDwtLogger().error( __FILE__, __LINE__,  "Widget windowProc2 {}", str ).flush;
1797     }
1798 
1799     switch (user_data) {
1800         case DELETE_RANGE:
1801             trace( "DELETE_RANGE" );
1802             return gtk_delete_range (handle, arg0, arg1);
1803         case DELETE_TEXT:
1804             trace( "DELETE_TEXT" );
1805             return gtk_delete_text (handle, arg0, arg1);
1806         case ROW_ACTIVATED:
1807             trace( "ROW_ACTIVATED" );
1808             gtk_row_activated (cast(GtkTreeView*)handle, cast(GtkTreePath*)arg0, cast(GtkTreeViewColumn*)arg1);
1809             return 0;
1810         case SCROLL_CHILD:
1811             trace( "SCROLL_CHILD" );
1812             return gtk_scroll_child (handle, arg0, arg1);
1813         case SWITCH_PAGE:
1814             trace( "SWITCH_PAGE" );
1815             return gtk_switch_page (handle, arg0, arg1);
1816         case TEST_COLLAPSE_ROW:
1817             trace( "TEST_COLLAPSE_ROW" );
1818             return gtk_test_collapse_row (cast(GtkTreeView*)handle, cast(GtkTreeIter*)arg0, cast(GtkTreePath*)arg1);
1819         case TEST_EXPAND_ROW:
1820             trace( "TEST_EXPAND_ROW" );
1821             return gtk_test_expand_row(cast(GtkTreeView*)handle, cast(GtkTreeIter*)arg0, cast(GtkTreePath*)arg1);
1822         default:
1823             trace( "default" );
1824             return 0;
1825     }
1826 }
1827 
1828 int windowProc (GtkWidget* handle, ptrdiff_t arg0, ptrdiff_t arg1, ptrdiff_t arg2, ptrdiff_t user_data) {
1829     void trace( String str ){
1830         version(LOG) getDwtLogger().error( __FILE__, __LINE__,  "Widget windowProc3 {}", str ).flush;
1831     }
1832 
1833     switch (user_data) {
1834         case EXPAND_COLLAPSE_CURSOR_ROW:
1835             trace( "EXPAND_COLLAPSE_CURSOR_ROW" );
1836             return gtk_expand_collapse_cursor_row (handle, arg0, arg1, arg2);
1837         case INSERT_TEXT:
1838             trace( "INSERT_TEXT" );
1839             return gtk_insert_text (cast(GtkEditable*)handle, cast(char*)arg0, arg1, arg2);
1840         case TEXT_BUFFER_INSERT_TEXT:
1841             trace( "TEXT_BUFFER_INSERT_TEXT" );
1842             return gtk_text_buffer_insert_text (cast(GtkTextBuffer*)handle, cast(GtkTextIter*)arg0, cast(char*)arg1, arg2);
1843         default:
1844             trace( "default" );
1845             return 0;
1846     }
1847 }
1848 
1849 }