Source code: org/eclipse/swt/widgets/Control.java
1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.swt.widgets;
12
13
14 import org.eclipse.swt.*;
15 import org.eclipse.swt.internal.Converter;
16 import org.eclipse.swt.internal.gtk.*;
17 import org.eclipse.swt.graphics.*;
18 import org.eclipse.swt.events.*;
19 import org.eclipse.swt.accessibility.*;
20
21 /**
22 * Control is the abstract superclass of all windowed user interface classes.
23 * <p>
24 * <dl>
25 * <dt><b>Styles:</b>
26 * <dd>BORDER</dd>
27 * <dd>LEFT_TO_RIGHT, RIGHT_TO_LEFT</dd>
28 * <dt><b>Events:</b>
29 * <dd>FocusIn, FocusOut, Help, KeyDown, KeyUp, MouseDoubleClick, MouseDown, MouseEnter,
30 * MouseExit, MouseHover, MouseUp, MouseMove, Move, Paint, Resize, Traverse,
31 * DragDetect, MenuDetect</dd>
32 * </dl>
33 * <p>
34 * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified.
35 * </p><p>
36 * IMPORTANT: This class is intended to be subclassed <em>only</em>
37 * within the SWT implementation.
38 * </p>
39 */
40 public abstract class Control extends Widget implements Drawable {
41 long /*int*/ fixedHandle;
42 long /*int*/ redrawWindow, enableWindow;
43 int drawCount;
44 Composite parent;
45 Cursor cursor;
46 Menu menu;
47 Font font;
48 String toolTipText;
49 Object layoutData;
50 Accessible accessible;
51
52 Control () {
53 }
54
55 /**
56 * Constructs a new instance of this class given its parent
57 * and a style value describing its behavior and appearance.
58 * <p>
59 * The style value is either one of the style constants defined in
60 * class <code>SWT</code> which is applicable to instances of this
61 * class, or must be built by <em>bitwise OR</em>'ing together
62 * (that is, using the <code>int</code> "|" operator) two or more
63 * of those <code>SWT</code> style constants. The class description
64 * lists the style constants that are applicable to the class.
65 * Style bits are also inherited from superclasses.
66 * </p>
67 *
68 * @param parent a composite control which will be the parent of the new instance (cannot be null)
69 * @param style the style of control to construct
70 *
71 * @exception IllegalArgumentException <ul>
72 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
73 * </ul>
74 * @exception SWTException <ul>
75 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
76 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
77 * </ul>
78 *
79 * @see SWT#BORDER
80 * @see Widget#checkSubclass
81 * @see Widget#getStyle
82 */
83 public Control (Composite parent, int style) {
84 super (parent, style);
85 this.parent = parent;
86 createWidget (0);
87 }
88
89 long /*int*/ defaultFont () {
90 return display.defaultFont;
91 }
92
93 void deregister () {
94 super.deregister ();
95 if (fixedHandle != 0) display.removeWidget (fixedHandle);
96 long /*int*/ imHandle = imHandle ();
97 if (imHandle != 0) display.removeWidget (imHandle);
98 }
99
100 boolean drawGripper (int x, int y, int width, int height) {
101 long /*int*/ paintHandle = paintHandle ();
102 long /*int*/ window = OS.GTK_WIDGET_WINDOW (paintHandle);
103 if (window == 0) return false;
104 long /*int*/ style = OS.gtk_widget_get_style (paintHandle);
105 if (style == 0) return false;
106 byte[] detail = Converter.wcsToMbcs (null, "", true);
107 OS.gtk_paint_handle (style, window, OS.GTK_STATE_NORMAL, OS.GTK_SHADOW_OUT, null, paintHandle, detail, x, y, width, height, OS.GTK_ORIENTATION_VERTICAL);
108 return true;
109 }
110
111 void enableWidget (boolean enabled) {
112 OS.gtk_widget_set_sensitive (handle, enabled);
113 }
114
115 long /*int*/ eventHandle () {
116 return handle;
117 }
118
119 void fixFocus (Control focusControl) {
120 Shell shell = getShell ();
121 Control control = this;
122 while ((control = control.parent) != null) {
123 if (control.setFocus ()) return;
124 if (control == shell) break;
125 }
126 shell.setSavedFocus (focusControl);
127 long /*int*/ focusHandle = shell.fixedHandle;
128 OS.GTK_WIDGET_SET_FLAGS (focusHandle, OS.GTK_CAN_FOCUS);
129 OS.gtk_widget_grab_focus (focusHandle);
130 OS.GTK_WIDGET_UNSET_FLAGS (focusHandle, OS.GTK_CAN_FOCUS);
131 }
132
133 long /*int*/ focusHandle () {
134 return handle;
135 }
136
137 long /*int*/ fontHandle () {
138 return handle;
139 }
140
141 boolean hasFocus () {
142 return this == display.getFocusControl();
143 }
144
145 void hookEvents () {
146 long /*int*/ windowProc2 = display.windowProc2;
147 long /*int*/ windowProc3 = display.windowProc3;
148
149 /* Connect the keyboard signals */
150 long /*int*/ focusHandle = focusHandle ();
151 int focusMask = OS.GDK_KEY_PRESS_MASK | OS.GDK_KEY_RELEASE_MASK | OS.GDK_FOCUS_CHANGE_MASK;
152 OS.gtk_widget_add_events (focusHandle, focusMask);
153 OS.g_signal_connect (focusHandle, OS.popup_menu, windowProc2, POPUP_MENU);
154 OS.g_signal_connect (focusHandle, OS.show_help, windowProc3, SHOW_HELP);
155 OS.g_signal_connect (focusHandle, OS.key_press_event, windowProc3, KEY_PRESS_EVENT);
156 OS.g_signal_connect (focusHandle, OS.key_release_event, windowProc3, KEY_RELEASE_EVENT);
157 OS.g_signal_connect (focusHandle, OS.focus, windowProc3, FOCUS);
158 OS.g_signal_connect (focusHandle, OS.focus_in_event, windowProc3, FOCUS_IN_EVENT);
159 OS.g_signal_connect (focusHandle, OS.focus_out_event, windowProc3, FOCUS_OUT_EVENT);
160
161 /* Connect the mouse signals */
162 long /*int*/ eventHandle = eventHandle ();
163 int eventMask = OS.GDK_POINTER_MOTION_MASK | OS.GDK_BUTTON_PRESS_MASK |
164 OS.GDK_BUTTON_RELEASE_MASK | OS.GDK_ENTER_NOTIFY_MASK |
165 OS.GDK_LEAVE_NOTIFY_MASK;
166 OS.gtk_widget_add_events (eventHandle, eventMask);
167 OS.g_signal_connect (eventHandle, OS.button_press_event, windowProc3, BUTTON_PRESS_EVENT);
168 OS.g_signal_connect (eventHandle, OS.button_release_event, windowProc3, BUTTON_RELEASE_EVENT);
169 OS.g_signal_connect (eventHandle, OS.motion_notify_event, windowProc3, MOTION_NOTIFY_EVENT);
170 OS.g_signal_connect (eventHandle, OS.enter_notify_event, windowProc3, ENTER_NOTIFY_EVENT);
171 OS.g_signal_connect (eventHandle, OS.leave_notify_event, windowProc3, LEAVE_NOTIFY_EVENT);
172 /*
173 * Feature in GTK. Events such as mouse move are propagate up
174 * the widget hierarchy and are seen by the parent. This is the
175 * correct GTK behavior but not correct for SWT. The fix is to
176 * hook a signal after and stop the propagation using a negative
177 * event number to distinguish this case.
178 */
179 OS.g_signal_connect_after (eventHandle, OS.button_press_event, windowProc3, -BUTTON_PRESS_EVENT);
180 OS.g_signal_connect_after (eventHandle, OS.button_release_event, windowProc3, -BUTTON_RELEASE_EVENT);
181 OS.g_signal_connect_after (eventHandle, OS.motion_notify_event, windowProc3, -MOTION_NOTIFY_EVENT);
182
183 /* Connect the event_after signal for both key and mouse */
184 OS.g_signal_connect (eventHandle, OS.event_after, windowProc3, EVENT_AFTER);
185 if (focusHandle != eventHandle) {
186 OS.g_signal_connect (focusHandle, OS.event_after, windowProc3, EVENT_AFTER);
187 }
188
189 /* Connect the paint signal */
190 long /*int*/ paintHandle = paintHandle ();
191 int paintMask = OS.GDK_EXPOSURE_MASK | OS.GDK_VISIBILITY_NOTIFY_MASK;
192 OS.gtk_widget_add_events (paintHandle, paintMask);
193 OS.g_signal_connect (paintHandle, OS.expose_event, windowProc3, -EXPOSE_EVENT);
194 OS.g_signal_connect (paintHandle, OS.visibility_notify_event, windowProc3, VISIBILITY_NOTIFY_EVENT);
195 OS.g_signal_connect_after (paintHandle, OS.expose_event, windowProc3, EXPOSE_EVENT);
196
197 /* Connect the Input Method signals */
198 OS.g_signal_connect_after (handle, OS.realize, windowProc2, REALIZE);
199 OS.g_signal_connect (handle, OS.unrealize, windowProc2, UNREALIZE);
200 long /*int*/ imHandle = imHandle ();
201 if (imHandle != 0) {
202 OS.g_signal_connect (imHandle, OS.commit, windowProc3, COMMIT);
203 OS.g_signal_connect (imHandle, OS.preedit_changed, windowProc2, PREEDIT_CHANGED);
204 }
205 }
206
207 long /*int*/ hoverProc (long /*int*/ widget) {
208 Event event = new Event ();
209 int [] x = new int [1], y = new int [1], mask = new int [1];
210 OS.gdk_window_get_pointer (0, x, y, mask);
211 event.x = x [0];
212 event.y = y [0];
213 long /*int*/ eventHandle = eventHandle ();
214 long /*int*/ window = OS.GTK_WIDGET_WINDOW (eventHandle);
215 OS.gdk_window_get_origin (window, x, y);
216 event.x -= x [0];
217 event.y -= y [0];
218 setInputState (event, mask [0]);
219 postEvent (SWT.MouseHover, event);
220 return 0;
221 }
222
223 long /*int*/ topHandle() {
224 if (fixedHandle != 0) return fixedHandle;
225 return super.topHandle ();
226 }
227
228 long /*int*/ paintHandle () {
229 long /*int*/ topHandle = topHandle ();
230 long /*int*/ paintHandle = handle;
231 while (paintHandle != topHandle) {
232 if ((OS.GTK_WIDGET_FLAGS (paintHandle) & OS.GTK_NO_WINDOW) == 0) break;
233 paintHandle = OS.gtk_widget_get_parent (paintHandle);
234 }
235 return paintHandle;
236 }
237
238 long /*int*/ paintWindow () {
239 long /*int*/ paintHandle = paintHandle ();
240 OS.gtk_widget_realize (paintHandle);
241 return OS.GTK_WIDGET_WINDOW (paintHandle);
242 }
243
244 /**
245 * Returns the preferred size of the receiver.
246 * <p>
247 * The <em>preferred size</em> of a control is the size that it would
248 * best be displayed at. The width hint and height hint arguments
249 * allow the caller to ask a control questions such as "Given a particular
250 * width, how high does the control need to be to show all of the contents?"
251 * To indicate that the caller does not wish to constrain a particular
252 * dimension, the constant <code>SWT.DEFAULT</code> is passed for the hint.
253 * </p>
254 *
255 * @param wHint the width hint (can be <code>SWT.DEFAULT</code>)
256 * @param hHint the height hint (can be <code>SWT.DEFAULT</code>)
257 * @return the preferred size of the control
258 *
259 * @exception SWTException <ul>
260 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
261 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
262 * </ul>
263 *
264 * @see Layout
265 * @see #getBorderWidth
266 * @see #getBounds
267 * @see #getSize
268 * @see #pack
269 * @see "computeTrim, getClientArea for controls that implement them"
270 */
271 public Point computeSize (int wHint, int hHint) {
272 return computeSize (wHint, hHint, true);
273 }
274
275 Control computeTabGroup () {
276 if (isTabGroup()) return this;
277 return parent.computeTabGroup ();
278 }
279
280 Control[] computeTabList() {
281 if (isTabGroup()) {
282 if (getVisible() && getEnabled()) {
283 return new Control[] {this};
284 }
285 }
286 return new Control[0];
287 }
288
289 Control computeTabRoot () {
290 Control[] tabList = parent._getTabList();
291 if (tabList != null) {
292 int index = 0;
293 while (index < tabList.length) {
294 if (tabList [index] == this) break;
295 index++;
296 }
297 if (index == tabList.length) {
298 if (isTabGroup ()) return this;
299 }
300 }
301 return parent.computeTabRoot ();
302 }
303
304 void createWidget (int index) {
305 checkOrientation (parent);
306 super.createWidget (index);
307 setInitialSize ();
308 setZOrder (null, false);
309 }
310
311 /**
312 * Returns the preferred size of the receiver.
313 * <p>
314 * The <em>preferred size</em> of a control is the size that it would
315 * best be displayed at. The width hint and height hint arguments
316 * allow the caller to ask a control questions such as "Given a particular
317 * width, how high does the control need to be to show all of the contents?"
318 * To indicate that the caller does not wish to constrain a particular
319 * dimension, the constant <code>SWT.DEFAULT</code> is passed for the hint.
320 * </p><p>
321 * If the changed flag is <code>true</code>, it indicates that the receiver's
322 * <em>contents</em> have changed, therefore any caches that a layout manager
323 * containing the control may have been keeping need to be flushed. When the
324 * control is resized, the changed flag will be <code>false</code>, so layout
325 * manager caches can be retained.
326 * </p>
327 *
328 * @param wHint the width hint (can be <code>SWT.DEFAULT</code>)
329 * @param hHint the height hint (can be <code>SWT.DEFAULT</code>)
330 * @param changed <code>true</code> if the control's contents have changed, and <code>false</code> otherwise
331 * @return the preferred size of the control.
332 *
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 Layout
339 * @see #getBorderWidth
340 * @see #getBounds
341 * @see #getSize
342 * @see #pack
343 * @see "computeTrim, getClientArea for controls that implement them"
344 */
345 public Point computeSize (int wHint, int hHint, boolean changed) {
346 checkWidget();
347 if (wHint != SWT.DEFAULT && wHint < 0) wHint = 0;
348 if (hHint != SWT.DEFAULT && hHint < 0) hHint = 0;
349 return computeNativeSize (handle, wHint, hHint, changed);
350 }
351
352 Point computeNativeSize (long /*int*/ h, int wHint, int hHint, boolean changed) {
353 int width = OS.GTK_WIDGET_WIDTH (h);
354 int height = OS.GTK_WIDGET_HEIGHT (h);
355 OS.gtk_widget_set_size_request (h, -1, -1);
356 GtkRequisition requisition = new GtkRequisition ();
357 OS.gtk_widget_size_request (h, requisition);
358 OS.gtk_widget_set_size_request (h, width, height);
359 width = wHint == SWT.DEFAULT ? requisition.width : wHint;
360 height = hHint == SWT.DEFAULT ? requisition.height : hHint;
361 return new Point (width, height);
362 }
363
364 /**
365 * Returns the accessible object for the receiver.
366 * If this is the first time this object is requested,
367 * then the object is created and returned.
368 *
369 * @return the accessible object
370 *
371 * @exception SWTException <ul>
372 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
373 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
374 * </ul>
375 *
376 * @see Accessible#addAccessibleListener
377 * @see Accessible#addAccessibleControlListener
378 *
379 * @since 2.0
380 */
381 public Accessible getAccessible () {
382 checkWidget ();
383 if (accessible == null) {
384 accessible = Accessible.internal_new_Accessible (this);
385 }
386 return accessible;
387 }
388
389 /**
390 * Returns a rectangle describing the receiver's size and location
391 * relative to its parent (or its display if its parent is null),
392 * unless the receiver is a shell. In this case, the location is
393 * relative to the display.
394 *
395 * @return the receiver's bounding rectangle
396 *
397 * @exception SWTException <ul>
398 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
399 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
400 * </ul>
401 */
402 public Rectangle getBounds () {
403 checkWidget();
404 long /*int*/ topHandle = topHandle ();
405 int x = OS.GTK_WIDGET_X (topHandle);
406 int y = OS.GTK_WIDGET_Y (topHandle);
407 int width = OS.GTK_WIDGET_WIDTH (topHandle);
408 int height = OS.GTK_WIDGET_HEIGHT (topHandle);
409 return new Rectangle (x, y, width, height);
410 }
411
412 /**
413 * Sets the receiver's size and location to the rectangular
414 * area specified by the argument. The <code>x</code> and
415 * <code>y</code> fields of the rectangle are relative to
416 * the receiver's parent (or its display if its parent is null).
417 * <p>
418 * Note: Attempting to set the width or height of the
419 * receiver to a negative number will cause that
420 * value to be set to zero instead.
421 * </p>
422 *
423 * @param rect the new bounds for the receiver
424 *
425 * @exception SWTException <ul>
426 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
427 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
428 * </ul>
429 */
430 public void setBounds (Rectangle rect) {
431 checkWidget ();
432 if (rect == null) error (SWT.ERROR_NULL_ARGUMENT);
433 setBounds (rect.x, rect.y, rect.width, rect.height);
434 }
435
436 /**
437 * Sets the receiver's size and location to the rectangular
438 * area specified by the arguments. The <code>x</code> and
439 * <code>y</code> arguments are relative to the receiver's
440 * parent (or its display if its parent is null), unless
441 * the receiver is a shell. In this case, the <code>x</code>
442 * and <code>y</code> arguments are relative to the display.
443 * <p>
444 * Note: Attempting to set the width or height of the
445 * receiver to a negative number will cause that
446 * value to be set to zero instead.
447 * </p>
448 *
449 * @param x the new x coordinate for the receiver
450 * @param y the new y coordinate for the receiver
451 * @param width the new width for the receiver
452 * @param height the new height for the receiver
453 *
454 * @exception SWTException <ul>
455 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
456 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
457 * </ul>
458 */
459 public void setBounds (int x, int y, int width, int height) {
460 checkWidget();
461 setBounds (x, y, width, height, true, true);
462 }
463
464 void moveHandle (int x, int y) {
465 long /*int*/ topHandle = topHandle ();
466 long /*int*/ parentHandle = parent.parentingHandle ();
467 OS.gtk_fixed_move (parentHandle, topHandle, x, y);
468 }
469
470 void resizeHandle (int width, int height) {
471 long /*int*/ topHandle = topHandle ();
472 OS.gtk_widget_set_size_request (topHandle, width, height);
473 if (topHandle != handle) {
474 OS.gtk_widget_set_size_request (handle, width, height);
475 }
476
477 /*
478 * Feature in GTK. Some widgets do not allocate the size
479 * of their internal children in gtk_widget_size_allocate().
480 * Instead this is done in gtk_widget_size_request(). This
481 * means that the client area of the widget is not correct.
482 * The fix is to call gtk_widget_size_request() (and throw
483 * the results away).
484 *
485 * Note: The following widgets rely on this feature:
486 * GtkScrolledWindow
487 * GtkNotebook
488 * GtkFrame
489 * GtkCombo
490 */
491 GtkRequisition requisition = new GtkRequisition ();
492 OS.gtk_widget_size_request (handle, requisition);
493 }
494
495 boolean setBounds (int x, int y, int width, int height, boolean move, boolean resize) {
496 long /*int*/ topHandle = topHandle ();
497 int flags = OS.GTK_WIDGET_FLAGS (topHandle);
498 OS.GTK_WIDGET_SET_FLAGS (topHandle, OS.GTK_VISIBLE);
499 boolean sameOrigin = true, sameExtent = true;
500 if (move) {
501 int oldX = OS.GTK_WIDGET_X (topHandle);
502 int oldY = OS.GTK_WIDGET_Y (topHandle);
503 sameOrigin = x == oldX && y == oldY;
504 if (!sameOrigin) {
505 if (enableWindow != 0) {
506 OS.gdk_window_move (enableWindow, x, y);
507 }
508 moveHandle (x, y);
509 }
510 }
511 if (resize) {
512 width = Math.max (1, width);
513 height = Math.max (1, height);
514 int oldWidth = OS.GTK_WIDGET_WIDTH (topHandle);
515 int oldHeight = OS.GTK_WIDGET_HEIGHT (topHandle);
516 sameExtent = width == oldWidth && height == oldHeight;
517 if (!sameExtent) {
518 if (redrawWindow != 0) {
519 OS.gdk_window_resize (redrawWindow, width, height);
520 }
521 if (enableWindow != 0) {
522 OS.gdk_window_resize (enableWindow, width, height);
523 }
524 resizeHandle (width, height);
525 }
526 }
527 if (!sameOrigin || !sameExtent) {
528 /*
529 * Force the container to allocate the size of its children.
530 */
531 long /*int*/ parentHandle = parent.parentingHandle ();
532 OS.gtk_container_resize_children (parentHandle);
533 }
534 if ((flags & OS.GTK_VISIBLE) == 0) {
535 OS.GTK_WIDGET_UNSET_FLAGS (topHandle, OS.GTK_VISIBLE);
536 }
537 if (!sameOrigin) sendEvent (SWT.Move);
538 if (!sameExtent) sendEvent (SWT.Resize);
539 return !sameOrigin || !sameExtent;
540 }
541
542 /**
543 * Returns a point describing the receiver's location relative
544 * to its parent (or its display if its parent is null), unless
545 * the receiver is a shell. In this case, the point is
546 * relative to the display.
547 *
548 * @return the receiver's location
549 *
550 * @exception SWTException <ul>
551 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
552 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
553 * </ul>
554 */
555 public Point getLocation () {
556 checkWidget();
557 long /*int*/ topHandle = topHandle ();
558 int x = OS.GTK_WIDGET_X (topHandle);
559 int y = OS.GTK_WIDGET_Y (topHandle);
560 return new Point (x, y);
561 }
562
563 /**
564 * Sets the receiver's location to the point specified by
565 * the arguments which are relative to the receiver's
566 * parent (or its display if its parent is null), unless
567 * the receiver is a shell. In this case, the point is
568 * relative to the display.
569 *
570 * @param location the new location for the receiver
571 *
572 * @exception SWTException <ul>
573 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
574 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
575 * </ul>
576 */
577 public void setLocation (Point location) {
578 checkWidget ();
579 if (location == null) error (SWT.ERROR_NULL_ARGUMENT);
580 setLocation (location.x, location.y);
581 }
582
583 /**
584 * Sets the receiver's location to the point specified by
585 * the arguments which are relative to the receiver's
586 * parent (or its display if its parent is null), unless
587 * the receiver is a shell. In this case, the point is
588 * relative to the display.
589 *
590 * @param x the new x coordinate for the receiver
591 * @param y the new y coordinate for the receiver
592 *
593 * @exception SWTException <ul>
594 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
595 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
596 * </ul>
597 */
598 public void setLocation(int x, int y) {
599 checkWidget();
600 setBounds (x, y, 0, 0, true, false);
601 }
602
603 /**
604 * Returns a point describing the receiver's size. The
605 * x coordinate of the result is the width of the receiver.
606 * The y coordinate of the result is the height of the
607 * receiver.
608 *
609 * @return the receiver's size
610 *
611 * @exception SWTException <ul>
612 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
613 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
614 * </ul>
615 */
616 public Point getSize () {
617 checkWidget();
618 long /*int*/ topHandle = topHandle ();
619 int width = OS.GTK_WIDGET_WIDTH (topHandle);
620 int height = OS.GTK_WIDGET_HEIGHT (topHandle);
621 return new Point (width, height);
622 }
623
624 /**
625 * Sets the receiver's size to the point specified by the argument.
626 * <p>
627 * Note: Attempting to set the width or height of the
628 * receiver to a negative number will cause them to be
629 * set to zero instead.
630 * </p>
631 *
632 * @param size the new size for the receiver
633 *
634 * @exception IllegalArgumentException <ul>
635 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
636 * </ul>
637 * @exception SWTException <ul>
638 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
639 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
640 * </ul>
641 */
642 public void setSize (Point size) {
643 checkWidget ();
644 if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
645 setSize (size.x, size.y);
646 }
647
648 /**
649 * Sets the receiver's size to the point specified by the arguments.
650 * <p>
651 * Note: Attempting to set the width or height of the
652 * receiver to a negative number will cause that
653 * value to be set to zero instead.
654 * </p>
655 *
656 * @param width the new width for the receiver
657 * @param height the new height for the receiver
658 *
659 * @exception SWTException <ul>
660 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
661 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
662 * </ul>
663 */
664 public void setSize (int width, int height) {
665 checkWidget();
666 setBounds (0, 0, width, height, false, true);
667 }
668
669 /**
670 * Moves the receiver above the specified control in the
671 * drawing order. If the argument is null, then the receiver
672 * is moved to the top of the drawing order. The control at
673 * the top of the drawing order will not be covered by other
674 * controls even if they occupy intersecting areas.
675 *
676 * @param control the sibling control (or null)
677 *
678 * @exception IllegalArgumentException <ul>
679 * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
680 * </ul>
681 * @exception SWTException <ul>
682 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
683 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
684 * </ul>
685 *
686 * @see #moveBelow
687 */
688 public void moveAbove (Control control) {
689 checkWidget();
690 if (control != null) {
691 if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
692 if (parent != control.parent) return;
693 }
694 setZOrder (control, true);
695 }
696
697 /**
698 * Moves the receiver below the specified control in the
699 * drawing order. If the argument is null, then the receiver
700 * is moved to the bottom of the drawing order. The control at
701 * the bottom of the drawing order will be covered by all other
702 * controls which occupy intersecting areas.
703 *
704 * @param control the sibling control (or null)
705 *
706 * @exception IllegalArgumentException <ul>
707 * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
708 * </ul>
709 * @exception SWTException <ul>
710 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
711 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
712 * </ul>
713 *
714 * @see #moveAbove
715 */
716 public void moveBelow (Control control) {
717 checkWidget();
718 if (control != null) {
719 if (control.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT);
720 if (parent != control.parent) return;
721 }
722 setZOrder (control, false);
723 }
724
725 /**
726 * Causes the receiver to be resized to its preferred size.
727 * For a composite, this involves computing the preferred size
728 * from its layout, if there is one.
729 *
730 * @exception SWTException <ul>
731 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
732 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
733 * </ul>
734 *
735 * @see #computeSize
736 */
737 public void pack () {
738 pack (true);
739 }
740
741 /**
742 * Causes the receiver to be resized to its preferred size.
743 * For a composite, this involves computing the preferred size
744 * from its layout, if there is one.
745 * <p>
746 * If the changed flag is <code>true</code>, it indicates that the receiver's
747 * <em>contents</em> have changed, therefore any caches that a layout manager
748 * containing the control may have been keeping need to be flushed. When the
749 * control is resized, the changed flag will be <code>false</code>, so layout
750 * manager caches can be retained.
751 * </p>
752 *
753 * @param changed whether or not the receiver's contents have changed
754 *
755 * @exception SWTException <ul>
756 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
757 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
758 * </ul>
759 *
760 * @see #computeSize
761 */
762 public void pack (boolean changed) {
763 setSize (computeSize (SWT.DEFAULT, SWT.DEFAULT, changed));
764 }
765
766 /**
767 * Sets the layout data associated with the receiver to the argument.
768 *
769 * @param layoutData the new layout data for the receiver.
770 *
771 * @exception SWTException <ul>
772 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
773 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
774 * </ul>
775 */
776 public void setLayoutData (Object layoutData) {
777 checkWidget();
778 this.layoutData = layoutData;
779 }
780
781 /**
782 * Returns a point which is the result of converting the
783 * argument, which is specified in display relative coordinates,
784 * to coordinates relative to the receiver.
785 * <p>
786 * @param x the x coordinate to be translated
787 * @param y the y coordinate to be translated
788 * @return the translated coordinates
789 *
790 * @exception SWTException <ul>
791 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
792 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
793 * </ul>
794 *
795 * @since 2.1
796 */
797 public Point toControl (int x, int y) {
798 checkWidget ();
799 long /*int*/ eventHandle = eventHandle ();
800 OS.gtk_widget_realize (eventHandle);
801 long /*int*/ window = OS.GTK_WIDGET_WINDOW (eventHandle);
802 int [] origin_x = new int [1], origin_y = new int [1];
803 OS.gdk_window_get_origin (window, origin_x, origin_y);
804 return new Point (x - origin_x [0], y - origin_y [0]);
805 }
806
807 /**
808 * Returns a point which is the result of converting the
809 * argument, which is specified in display relative coordinates,
810 * to coordinates relative to the receiver.
811 * <p>
812 * @param point the point to be translated (must not be null)
813 * @return the translated coordinates
814 *
815 * @exception IllegalArgumentException <ul>
816 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
817 * </ul>
818 * @exception SWTException <ul>
819 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
820 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
821 * </ul>
822 */
823 public Point toControl (Point point) {
824 checkWidget ();
825 if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
826 return toControl (point.x, point.y);
827 }
828
829 /**
830 * Returns a point which is the result of converting the
831 * argument, which is specified in coordinates relative to
832 * the receiver, to display relative coordinates.
833 * <p>
834 * @param x the x coordinate to be translated
835 * @param y the y coordinate to be translated
836 * @return the translated coordinates
837 *
838 * @exception SWTException <ul>
839 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
840 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
841 * </ul>
842 *
843 * @since 2.1
844 */
845 public Point toDisplay (int x, int y) {
846 checkWidget();
847 long /*int*/ eventHandle = eventHandle ();
848 OS.gtk_widget_realize (eventHandle);
849 long /*int*/ window = OS.GTK_WIDGET_WINDOW (eventHandle);
850 int [] origin_x = new int [1], origin_y = new int [1];
851 OS.gdk_window_get_origin (window, origin_x, origin_y);
852 return new Point (origin_x [0] + x, origin_y [0] + y);
853 }
854
855 /**
856 * Returns a point which is the result of converting the
857 * argument, which is specified in coordinates relative to
858 * the receiver, to display relative coordinates.
859 * <p>
860 * @param point the point to be translated (must not be null)
861 * @return the translated coordinates
862 *
863 * @exception IllegalArgumentException <ul>
864 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
865 * </ul>
866 * @exception SWTException <ul>
867 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
868 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
869 * </ul>
870 */
871 public Point toDisplay (Point point) {
872 checkWidget();
873 if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
874 return toDisplay (point.x, point.y);
875 }
876
877 /**
878 * Adds the listener to the collection of listeners who will
879 * be notified when the control is moved or resized, by sending
880 * it one of the messages defined in the <code>ControlListener</code>
881 * interface.
882 *
883 * @param listener the listener which should be notified
884 *
885 * @exception IllegalArgumentException <ul>
886 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
887 * </ul>
888 * @exception SWTException <ul>
889 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
890 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
891 * </ul>
892 *
893 * @see ControlListener
894 * @see #removeControlListener
895 */
896 public void addControlListener(ControlListener listener) {
897 checkWidget();
898 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
899 TypedListener typedListener = new TypedListener (listener);
900 addListener (SWT.Resize,typedListener);
901 addListener (SWT.Move,typedListener);
902 }
903
904 /**
905 * Adds the listener to the collection of listeners who will
906 * be notified when the control gains or loses focus, by sending
907 * it one of the messages defined in the <code>FocusListener</code>
908 * interface.
909 *
910 * @param listener the listener which should be notified
911 *
912 * @exception IllegalArgumentException <ul>
913 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
914 * </ul>
915 * @exception SWTException <ul>
916 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
917 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
918 * </ul>
919 *
920 * @see FocusListener
921 * @see #removeFocusListener
922 */
923 public void addFocusListener(FocusListener listener) {
924 checkWidget();
925 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
926 TypedListener typedListener = new TypedListener (listener);
927 addListener(SWT.FocusIn,typedListener);
928 addListener(SWT.FocusOut,typedListener);
929 }
930
931 /**
932 * Adds the listener to the collection of listeners who will
933 * be notified when help events are generated for the control,
934 * by sending it one of the messages defined in the
935 * <code>HelpListener</code> interface.
936 *
937 * @param listener the listener which should be notified
938 *
939 * @exception IllegalArgumentException <ul>
940 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
941 * </ul>
942 * @exception SWTException <ul>
943 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
944 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
945 * </ul>
946 *
947 * @see HelpListener
948 * @see #removeHelpListener
949 */
950 public void addHelpListener (HelpListener listener) {
951 checkWidget();
952 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
953 TypedListener typedListener = new TypedListener (listener);
954 addListener (SWT.Help, typedListener);
955 }
956
957 /**
958 * Adds the listener to the collection of listeners who will
959 * be notified when keys are pressed and released on the system keyboard, by sending
960 * it one of the messages defined in the <code>KeyListener</code>
961 * interface.
962 *
963 * @param listener the listener which should be notified
964 *
965 * @exception IllegalArgumentException <ul>
966 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
967 * </ul>
968 * @exception SWTException <ul>
969 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
970 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
971 * </ul>
972 *
973 * @see KeyListener
974 * @see #removeKeyListener
975 */
976 public void addKeyListener(KeyListener listener) {
977 checkWidget();
978 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
979 TypedListener typedListener = new TypedListener (listener);
980 addListener(SWT.KeyUp,typedListener);
981 addListener(SWT.KeyDown,typedListener);
982 }
983
984 /**
985 * Adds the listener to the collection of listeners who will
986 * be notified when mouse buttons are pressed and released, by sending
987 * it one of the messages defined in the <code>MouseListener</code>
988 * interface.
989 *
990 * @param listener the listener which should be notified
991 *
992 * @exception IllegalArgumentException <ul>
993 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
994 * </ul>
995 * @exception SWTException <ul>
996 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
997 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
998 * </ul>
999 *
1000 * @see MouseListener
1001 * @see #removeMouseListener
1002 */
1003public void addMouseListener(MouseListener listener) {
1004 checkWidget();
1005 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1006 TypedListener typedListener = new TypedListener (listener);
1007 addListener(SWT.MouseDown,typedListener);
1008 addListener(SWT.MouseUp,typedListener);
1009 addListener(SWT.MouseDoubleClick,typedListener);
1010}
1011
1012/**
1013 * Adds the listener to the collection of listeners who will
1014 * be notified when the mouse moves, by sending it one of the
1015 * messages defined in the <code>MouseMoveListener</code>
1016 * interface.
1017 *
1018 * @param listener the listener which should be notified
1019 *
1020 * @exception IllegalArgumentException <ul>
1021 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1022 * </ul>
1023 * @exception SWTException <ul>
1024 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1025 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1026 * </ul>
1027 *
1028 * @see MouseMoveListener
1029 * @see #removeMouseMoveListener
1030 */
1031public void addMouseMoveListener(MouseMoveListener listener) {
1032 checkWidget();
1033 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1034 TypedListener typedListener = new TypedListener (listener);
1035 addListener(SWT.MouseMove,typedListener);
1036}
1037
1038/**
1039 * Adds the listener to the collection of listeners who will
1040 * be notified when the mouse passes or hovers over controls, by sending
1041 * it one of the messages defined in the <code>MouseTrackListener</code>
1042 * interface.
1043 *
1044 * @param listener the listener which should be notified
1045 *
1046 * @exception IllegalArgumentException <ul>
1047 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1048 * </ul>
1049 * @exception SWTException <ul>
1050 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1051 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1052 * </ul>
1053 *
1054 * @see MouseTrackListener
1055 * @see #removeMouseTrackListener
1056 */
1057public void addMouseTrackListener (MouseTrackListener listener) {
1058 checkWidget();
1059 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1060 TypedListener typedListener = new TypedListener (listener);
1061 addListener (SWT.MouseEnter,typedListener);
1062 addListener (SWT.MouseExit,typedListener);
1063 addListener (SWT.MouseHover,typedListener);
1064}
1065
1066/**
1067 * Adds the listener to the collection of listeners who will
1068 * be notified when the receiver needs to be painted, by sending it
1069 * one of the messages defined in the <code>PaintListener</code>
1070 * interface.
1071 *
1072 * @param listener the listener which should be notified
1073 *
1074 * @exception IllegalArgumentException <ul>
1075 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1076 * </ul>
1077 * @exception SWTException <ul>
1078 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1079 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1080 * </ul>
1081 *
1082 * @see PaintListener
1083 * @see #removePaintListener
1084 */
1085public void addPaintListener(PaintListener listener) {
1086 checkWidget();
1087 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1088 TypedListener typedListener = new TypedListener (listener);
1089 addListener(SWT.Paint,typedListener);
1090}
1091
1092/**
1093 * Adds the listener to the collection of listeners who will
1094 * be notified when traversal events occur, by sending it
1095 * one of the messages defined in the <code>TraverseListener</code>
1096 * interface.
1097 *
1098 * @param listener the listener which should be notified
1099 *
1100 * @exception IllegalArgumentException <ul>
1101 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1102 * </ul>
1103 * @exception SWTException <ul>
1104 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1105 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1106 * </ul>
1107 *
1108 * @see TraverseListener
1109 * @see #removeTraverseListener
1110 */
1111public void addTraverseListener (TraverseListener listener) {
1112 checkWidget();
1113 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1114 TypedListener typedListener = new TypedListener (listener);
1115 addListener (SWT.Traverse,typedListener);
1116}
1117
1118/**
1119 * Removes the listener from the collection of listeners who will
1120 * be notified when the control is moved or resized.
1121 *
1122 * @param listener the listener which should be notified
1123 *
1124 * @exception IllegalArgumentException <ul>
1125 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1126 * </ul>
1127 * @exception SWTException <ul>
1128 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1129 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1130 * </ul>
1131 *
1132 * @see ControlListener
1133 * @see #addControlListener
1134 */
1135public void removeControlListener (ControlListener listener) {
1136 checkWidget();
1137 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1138 if (eventTable == null) return;
1139 eventTable.unhook (SWT.Move, listener);
1140 eventTable.unhook (SWT.Resize, listener);
1141}
1142/**
1143 * Removes the listener from the collection of listeners who will
1144 * be notified when the control gains or loses focus.
1145 *
1146 * @param listener the listener which should be notified
1147 *
1148 * @exception IllegalArgumentException <ul>
1149 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1150 * </ul>
1151 * @exception SWTException <ul>
1152 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1153 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1154 * </ul>
1155 *
1156 * @see FocusListener
1157 * @see #addFocusListener
1158 */
1159public void removeFocusListener(FocusListener listener) {
1160 checkWidget();
1161 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1162 if (eventTable == null) return;
1163 eventTable.unhook (SWT.FocusIn, listener);
1164 eventTable.unhook (SWT.FocusOut, listener);
1165}
1166/**
1167 * Removes the listener from the collection of listeners who will
1168 * be notified when the help events are generated for the control.
1169 *
1170 * @param listener the listener which should be notified
1171 *
1172 * @exception IllegalArgumentException <ul>
1173 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1174 * </ul>
1175 * @exception SWTException <ul>
1176 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1177 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1178 * </ul>
1179 *
1180 * @see HelpListener
1181 * @see #addHelpListener
1182 */
1183public void removeHelpListener (HelpListener listener) {
1184 checkWidget();
1185 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1186 if (eventTable == null) return;
1187 eventTable.unhook (SWT.Help, listener);
1188}
1189/**
1190 * Removes the listener from the collection of listeners who will
1191 * be notified when keys are pressed and released on the system keyboard.
1192 *
1193 * @param listener the listener which should 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 KeyListener
1204 * @see #addKeyListener
1205 */
1206public void removeKeyListener(KeyListener listener) {
1207 checkWidget();
1208 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1209 if (eventTable == null) return;
1210 eventTable.unhook (SWT.KeyUp, listener);
1211 eventTable.unhook (SWT.KeyDown, listener);
1212}
1213/**
1214 * Removes the listener from the collection of listeners who will
1215 * be notified when mouse buttons are pressed and released.
1216 *
1217 * @param listener the listener which should be notified
1218 *
1219 * @exception IllegalArgumentException <ul>
1220 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1221 * </ul>
1222 * @exception SWTException <ul>
1223 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1224 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1225 * </ul>
1226 *
1227 * @see MouseListener
1228 * @see #addMouseListener
1229 */
1230public void removeMouseListener (MouseListener listener) {
1231 checkWidget();
1232 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1233 if (eventTable == null) return;
1234 eventTable.unhook (SWT.MouseDown, listener);
1235 eventTable.unhook (SWT.MouseUp, listener);
1236 eventTable.unhook (SWT.MouseDoubleClick, listener);
1237}
1238/**
1239 * Removes the listener from the collection of listeners who will
1240 * be notified when the mouse moves.
1241 *
1242 * @param listener the listener which should be notified
1243 *
1244 * @exception IllegalArgumentException <ul>
1245 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1246 * </ul>
1247 * @exception SWTException <ul>
1248 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1249 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1250 * </ul>
1251 *
1252 * @see MouseMoveListener
1253 * @see #addMouseMoveListener
1254 */
1255public void removeMouseMoveListener(MouseMoveListener listener) {
1256 checkWidget();
1257 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1258 if (eventTable == null) return;
1259 eventTable.unhook (SWT.MouseMove, listener);
1260}
1261
1262/**
1263 * Removes the listener from the collection of listeners who will
1264 * be notified when the mouse passes or hovers over controls.
1265 *
1266 * @param listener the listener which should be notified
1267 *
1268 * @exception IllegalArgumentException <ul>
1269 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1270 * </ul>
1271 * @exception SWTException <ul>
1272 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1273 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1274 * </ul>
1275 *
1276 * @see MouseTrackListener
1277 * @see #addMouseTrackListener
1278 */
1279public void removeMouseTrackListener(MouseTrackListener listener) {
1280 checkWidget();
1281 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1282 if (eventTable == null) return;
1283 eventTable.unhook (SWT.MouseEnter, listener);
1284 eventTable.unhook (SWT.MouseExit, listener);
1285 eventTable.unhook (SWT.MouseHover, listener);
1286}
1287
1288/**
1289 * Removes the listener from the collection of listeners who will
1290 * be notified when the receiver needs to be painted.
1291 *
1292 * @param listener the listener which should be notified
1293 *
1294 * @exception IllegalArgumentException <ul>
1295 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1296 * </ul>
1297 * @exception SWTException <ul>
1298 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1299 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1300 * </ul>
1301 *
1302 * @see PaintListener
1303 * @see #addPaintListener
1304 */
1305public void removePaintListener(PaintListener listener) {
1306 checkWidget();
1307 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1308 if (eventTable == null) return;
1309 eventTable.unhook(SWT.Paint, listener);
1310}
1311
1312/**
1313 * Removes the listener from the collection of listeners who will
1314 * be notified when traversal events occur.
1315 *
1316 * @param listener the listener which should be notified
1317 *
1318 * @exception IllegalArgumentException <ul>
1319 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1320 * </ul>
1321 * @exception SWTException <ul>
1322 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1323 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1324 * </ul>
1325 *
1326 * @see TraverseListener
1327 * @see #addTraverseListener
1328 */
1329public void removeTraverseListener(TraverseListener listener) {
1330 checkWidget ();
1331 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1332 if (eventTable == null) return;
1333 eventTable.unhook (SWT.Traverse, listener);
1334}
1335
1336boolean filterKey (int keyval, long /*int*/ event) {
1337 long /*int*/ imHandle = imHandle ();
1338 if (imHandle != 0) {
1339 return OS.gtk_im_context_filter_keypress (imHandle, event);
1340 }
1341 return false;
1342}
1343
1344Menu [] findMenus (Control control) {
1345 if (menu != null && this != control) return new Menu [] {menu};
1346 return new Menu [0];
1347}
1348
1349void fixChildren (Shell newShell, Shell oldShell, Decorations newDecorations, Decorations oldDecorations, Menu [] menus) {
1350 oldShell.fixShell (newShell, this);
1351 oldDecorations.fixDecorations (newDecorations, this, menus);
1352}
1353
1354/**
1355 * Forces the receiver to have the <em>keyboard focus</em>, causing
1356 * all keyboard events to be delivered to it.
1357 *
1358 * @return <code>true</code> if the control got focus, and <code>false</code> if it was unable to.
1359 *
1360 * @exception SWTException <ul>
1361 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1362 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1363 * </ul>
1364 *
1365 * @see #setFocus
1366 */
1367public boolean forceFocus () {
1368 checkWidget();
1369 Shell shell = getShell ();
1370 shell.setSavedFocus (this);
1371 if (!isEnabled () || !isVisible ()) return false;
1372 shell.bringToTop (false);
1373 return forceFocus (focusHandle ());
1374}
1375
1376boolean forceFocus (long /*int*/ focusHandle) {
1377 OS.gtk_widget_grab_focus (focusHandle);
1378 return this == display.getFocusControl();
1379}
1380
1381/**
1382 * Returns the receiver's background color.
1383 *
1384 * @return the background color
1385 *
1386 * @exception SWTException <ul>
1387 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1388 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1389 * </ul>
1390 */
1391public Color getBackground () {
1392 checkWidget();
1393 return Color.gtk_new (display, getBackgroundColor ());
1394}
1395
1396GdkColor getBackgroundColor () {
1397 return getBgColor ();
1398}
1399
1400GdkColor getBgColor () {
1401 long /*int*/ fontHandle = fontHandle ();
1402 OS.gtk_widget_realize (fontHandle);
1403 GdkColor color = new GdkColor ();
1404 OS.gtk_style_get_bg (OS.gtk_widget_get_style (fontHandle), OS.GTK_STATE_NORMAL, color);
1405 return color;
1406}
1407
1408GdkColor getBaseColor () {
1409 long /*int*/ fontHandle = fontHandle ();
1410 OS.gtk_widget_realize (fontHandle);
1411 GdkColor color = new GdkColor ();
1412 OS.gtk_style_get_base (OS.gtk_widget_get_style (fontHandle), OS.GTK_STATE_NORMAL, color);
1413 return color;
1414}
1415
1416/**
1417 * Returns the receiver's border width.
1418 *
1419 * @return the border width
1420 *
1421 * @exception SWTException <ul>
1422 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1423 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1424 * </ul>
1425 */
1426public int getBorderWidth () {
1427 checkWidget();
1428 return 0;
1429}
1430
1431/**
1432 * Returns <code>true</code> if the receiver is enabled, and
1433 * <code>false</code> otherwise. A disabled control is typically
1434 * not selectable from the user interface and draws with an
1435 * inactive or "grayed" look.
1436 *
1437 * @return the receiver's enabled state
1438 *
1439 * @exception SWTException <ul>
1440 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1441 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1442 * </ul>
1443 *
1444 * @see #isEnabled
1445 */
1446public boolean getEnabled () {
1447 checkWidget ();
1448 return (state & DISABLED) == 0;
1449}
1450
1451/**
1452 * Returns the font that the receiver will use to paint textual information.
1453 *
1454 * @return the receiver's font
1455 *
1456 * @exception SWTException <ul>
1457 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1458 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1459 * </ul>
1460 */
1461public Font getFont () {
1462 checkWidget();
1463 if (font != null) return font;
1464 return Font.gtk_new (display, defaultFont ());
1465}
1466
1467long /*int*/ getFontDescription () {
1468 long /*int*/ fontHandle = fontHandle ();
1469 return OS.gtk_style_get_font_desc (OS.gtk_widget_get_style (fontHandle));
1470}
1471
1472/**
1473 * Returns the foreground color that the receiver will use to draw.
1474 *
1475 * @return the receiver's foreground color
1476 *
1477 * @exception SWTException <ul>
1478 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1479 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1480 * </ul>
1481 */
1482public Color getForeground () {
1483 checkWidget();
1484 return Color.gtk_new (display, getForegroundColor ());
1485}
1486
1487GdkColor getForegroundColor () {
1488 return getFgColor ();
1489}
1490
1491GdkColor getFgColor () {
1492 long /*int*/ fontHandle = fontHandle ();
1493 OS.gtk_widget_realize (fontHandle);
1494 GdkColor color = new GdkColor ();
1495 OS.gtk_style_get_fg (OS.gtk_widget_get_style (fontHandle), OS.GTK_STATE_NORMAL, color);
1496 return color;
1497}
1498
1499Point getIMCaretPos () {
1500 return new Point (0, 0);
1501}
1502
1503GdkColor getTextColor () {
1504 long /*int*/ fontHandle = fontHandle ();
1505 OS.gtk_widget_realize (fontHandle);
1506 GdkColor color = new GdkColor ();
1507 OS.gtk_style_get_text (OS.gtk_widget_get_style (fontHandle), OS.GTK_STATE_NORMAL, color);
1508 return color;
1509}
1510
1511/**
1512 * Returns layout data which is associated with the receiver.
1513 *
1514 * @return the receiver's layout data
1515 *
1516 * @exception SWTException <ul>
1517 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1518 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1519 * </ul>
1520 */
1521public Object getLayoutData () {
1522 checkWidget();
1523 return layoutData;
1524}
1525
1526/**
1527 * Returns the receiver's pop up menu if it has one, or null
1528 * if it does not. All controls may optionally have a pop up
1529 * menu that is displayed when the user requests one for
1530 * the control. The sequence of key strokes, button presses
1531 * and/or button releases that are used to request a pop up
1532 * menu is platform specific.
1533 *
1534 * @return the receiver's menu
1535 *
1536 * @exception SWTException <ul>
1537 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1538 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1539 * </ul>
1540 */
1541public Menu getMenu () {
1542 checkWidget();
1543 return menu;
1544}
1545
1546/**
1547 * Returns the receiver's monitor.
1548 *
1549 * @return the receiver's monitor
1550 *
1551 * @since 3.0
1552 */
1553public Monitor getMonitor () {
1554 checkWidget();
1555 Monitor monitor = null;
1556 long /*int*/ screen = OS.gdk_screen_get_default ();
1557 if (screen != 0) {
1558 int monitorNumber = OS.gdk_screen_get_monitor_at_window (screen, paintWindow ());
1559 GdkRectangle dest = new GdkRectangle ();
1560 OS.gdk_screen_get_monitor_geometry (screen, monitorNumber, dest);
1561 monitor = new Monitor ();
1562 monitor.handle = monitorNumber;
1563 monitor.x = dest.x;
1564 monitor.y = dest.y;
1565 monitor.width = dest.width;
1566 monitor.height = dest.height;
1567 monitor.clientX = monitor.x;
1568 monitor.clientY = monitor.y;
1569 monitor.clientWidth = monitor.width;
1570 monitor.clientHeight = monitor.height;
1571 } else {
1572 monitor = display.getPrimaryMonitor ();
1573 }
1574 return monitor;
1575}
1576
1577/**
1578 * Returns the receiver's parent, which must be a <code>Composite</code>
1579 * or null when the receiver is a shell that was created with null or
1580 * a display for a parent.
1581 *
1582 * @return the receiver's parent
1583 *
1584 * @exception SWTException <ul>
1585 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1586 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1587 * </ul>
1588 */
1589public Composite getParent () {
1590 checkWidget();
1591 return parent;
1592}
1593
1594Control [] getPath () {
1595 int count = 0;
1596 Shell shell = getShell ();
1597 Control control = this;
1598 while (control != shell) {
1599 count++;
1600 control = control.parent;
1601 }
1602 control = this;
1603 Control [] result = new Control [count];
1604 while (control != shell) {
1605 result [--count] = control;
1606 control = control.parent;
1607 }
1608 return result;
1609}
1610
1611/**
1612 * Returns the receiver's shell. For all controls other than
1613 * shells, this simply returns the control's nearest ancestor
1614 * shell. Shells return themselves, even if they are children
1615 * of other shells.
1616 *
1617 * @return the receiver's shell
1618 *
1619 * @exception SWTException <ul>
1620 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1621 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1622 * </ul>
1623 *
1624 * @see #getParent
1625 */
1626public Shell getShell() {
1627 checkWidget();
1628 return _getShell();
1629}
1630Shell _getShell() {
1631 return parent._getShell();
1632}
1633
1634/**
1635 * Returns the receiver's tool tip text, or null if it has
1636 * not been set.
1637 *
1638 * @return the receiver's tool tip text
1639 *
1640 * @exception SWTException <ul>
1641 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1642 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1643 * </ul>
1644 */
1645public String getToolTipText () {
1646 checkWidget();
1647 return toolTipText;
1648}
1649/**
1650 * Returns <code>true</code> if the receiver is visible, and
1651 * <code>false</code> otherwise.
1652 * <p>
1653 * If one of the receiver's ancestors is not visible or some
1654 * other condition makes the receiver not visible, this method
1655 * may still indicate that it is considered visible even though
1656 * it may not actually be showing.
1657 * </p>
1658 *
1659 * @return the receiver's visibility state
1660 *
1661 * @exception SWTException <ul>
1662 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1663 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1664 * </ul>
1665 */
1666public boolean getVisible () {
1667 checkWidget();
1668 return OS.GTK_WIDGET_VISIBLE (topHandle ());
1669}
1670
1671long /*int*/ gtk_button_press_event (long /*int*/ widget, long /*int*/ event) {
1672 Shell shell = _getShell ();
1673 GdkEventButton gdkEvent = new GdkEventButton ();
1674 OS.memmove (gdkEvent, event, GdkEventButton.sizeof);
1675 if (gdkEvent.type == OS.GDK_3BUTTON_PRESS) return 0;
1676 display.dragStartX = (int) gdkEvent.x;
1677 display.dragStartY = (int) gdkEvent.y;
1678 display.dragging = false;
1679 int button = gdkEvent.button;
1680 int type = gdkEvent.type != OS.GDK_2BUTTON_PRESS ? SWT.MouseDown : SWT.MouseDoubleClick;
1681 sendMouseEvent (type, button, event);
1682 int result = 0;
1683 if ((state & MENU) != 0) {
1684 if (gdkEvent.button == 3 && gdkEvent.type == OS.GDK_BUTTON_PRESS) {
1685 if (showMenu ((int)gdkEvent.x_root, (int)gdkEvent.y_root)) {
1686 result = 1;
1687 }
1688 }
1689 }
1690
1691 /*
1692 * It is possible that the shell may be
1693 * disposed at this point. If this happens
1694 * don't send the activate and deactivate
1695 * events.
1696 */
1697 if (!shell.isDisposed ()) {
1698 shell.setActiveControl (this);
1699 }
1700 return result;
1701}
1702
1703long /*int*/ gtk_button_release_event (long /*int*/ widget, long /*int*/ event) {
1704 GdkEventButton gdkEvent = new GdkEventButton ();
1705 OS.memmove (gdkEvent, event, GdkEventButton.sizeof);
1706 sendMouseEvent (SWT.MouseUp, gdkEvent.button, event);
1707 return 0;
1708}
1709
1710long /*int*/ gtk_commit (long /*int*/ imcontext, long /*int*/ text) {
1711 if (text == 0) return 0;
1712 int length = OS.strlen (text);
1713 if (length == 0) return 0;
1714 byte [] buffer = new byte [length];
1715 OS.memmove (buffer, text, length);
1716 char [] chars = Converter.mbcsToWcs (null, buffer);
1717 sendIMKeyEvent (SWT.KeyDown, null, chars);
1718 return 0;
1719}
1720
1721long /*int*/ gtk_enter_notify_event (long /*int*/ widget, long /*int*/ event) {
1722 GdkEventCrossing gdkEvent = new GdkEventCrossing ();
1723 OS.memmove (gdkEvent, event, GdkEventCrossing.sizeof);
1724 if (gdkEvent.mode != OS.GDK_CROSSING_NORMAL) return 0;
1725 if (gdkEvent.subwindow != 0) return 0;
1726 sendMouseEvent (SWT.MouseEnter, 0, event);
1727 return 0;
1728}
1729
1730long /*int*/ gtk_event_after (long /*int*/ widget, long /*int*/ gdkEvent) {
1731 GdkEvent event = new GdkEvent ();
1732 OS.memmove (event, gdkEvent, GdkEvent.sizeof);
1733 switch (event.type) {
1734 case OS.GDK_BUTTON_PRESS: {
1735 if ((state & MENU) == 0) {
1736 GdkEventButton gdkEventButton = new GdkEventButton ();
1737 OS.memmove (gdkEventButton, gdkEvent, GdkEventButton.sizeof);
1738 if (gdkEventButton.button == 3) {
1739 showMenu ((int) gdkEventButton.x_root, (int) gdkEventButton.y_root);
1740 }
1741 }
1742 break;
1743 }
1744 case OS.GDK_FOCUS_CHANGE: {
1745 GdkEventFocus gdkEventFocus = new GdkEventFocus ();
1746 OS.memmove (gdkEventFocus, gdkEvent, GdkEventFocus.sizeof);
1747 sendFocusEvent (gdkEventFocus.in != 0 ? SWT.FocusIn : SWT.FocusOut);
1748 break;
1749 }
1750 }
1751 return 0;
1752}
1753
1754long /*int*/ gtk_expose_event (long /*int*/ widget, long /*int*/ eventPtr) {
1755 if ((state & OBSCURED) != 0) return 0;
1756 if (!hooks (SWT.Paint) && !filters (SWT.Paint)) return 0;
1757 GdkEventExpose gdkEvent = new GdkEventExpose ();
1758 OS.memmove(gdkEvent, eventPtr, GdkEventExpose.sizeof);
1759 Event event = new Event ();
1760 event.count = gdkEvent.count;
1761 event.x = gdkEvent.area_x;
1762 event.y = gdkEvent.area_y;
1763 event.width = gdkEvent.area_width;
1764 event.height = gdkEvent.area_height;
1765 GC gc = event.gc = new GC (this);
1766 Region region = Region.gtk_new (display, gdkEvent.region);
1767 gc.setClipping (region);
1768 sendEvent (SWT.Paint, event);
1769 gc.dispose ();
1770 event.gc = null;
1771 return 0;
1772}
1773
1774long /*int*/ gtk_focus (long /*int*/ widget, long /*int*/ directionType) {
1775 /* Stop GTK traversal for every widget */
1776 return 1;
1777}
1778
1779long /*int*/ gtk_focus_in_event (long /*int*/ widget, long /*int*/ event) {
1780 // widget could be disposed at this point
1781 if (handle != 0) {
1782 Control oldControl = display.imControl;
1783 if (oldControl != this) {
1784 if (oldControl != null && !oldControl.isDisposed ()) {
1785 long /*int*/ oldIMHandle = oldControl.imHandle ();
1786 if (oldIMHandle != 0) OS.gtk_im_context_reset (oldIMHandle);
1787 }
1788 }
1789 if (hooks (SWT.KeyDown) || hooks (SWT.KeyUp)) {
1790 long /*int*/ imHandle = imHandle ();
1791 if (imHandle != 0) OS.gtk_im_context_focus_in (imHandle);
1792 }
1793 }
1794 return 0;
1795}
1796
1797long /*int*/ gtk_focus_out_event (long /*int*/ widget, long /*int*/ event) {
1798 // widget could be disposed at this point
1799 if (handle != 0) {
1800 if (hooks (SWT.KeyDown) || hooks (SWT.KeyUp)) {
1801 long /*int*/ imHandle = imHandle ();
1802 if (imHandle != 0) {
1803 OS.gtk_im_context_focus_out (imHandle);
1804 }
1805 }
1806 }
1807 return 0;
1808}
1809
1810long /*int*/ gtk_key_press_event (long /*int*/ widget, long /*int*/ event) {
1811 if (!hasFocus ()) return 0;
1812 GdkEventKey gdkEvent = new GdkEventKey ();
1813 OS.memmove (gdkEvent, event, GdkEventKey.sizeof);
1814
1815 if (translateMnemonic (gdkEvent.keyval, gdkEvent)) return 1;
1816 // widget could be disposed at this point
1817 if (isDisposed ()) return 0;
1818
1819 if (filterKey (gdkEvent.keyval, event)) return 1;
1820 // widget could be disposed at this point
1821 if (isDisposed ()) return 0;
1822
1823 if (translateTraversal (gdkEvent)) return 1;
1824 // widget could be disposed at this point
1825 if (isDisposed ()) return 0;
1826 return sendKeyEvent (SWT.KeyDown, gdkEvent) ? 0 : 1;
1827}
1828
1829long /*int*/ gtk_key_release_event (long /*int*/ widget, long /*int*/ event) {
1830 if (!hasFocus ()) return 0;
1831 long /*int*/ imHandle = imHandle ();
1832 if (imHandle != 0) {
1833 if (OS.gtk_im_context_filter_keypress (imHandle, event)) return 1;
1834 }
1835 GdkEventKey gdkEvent = new GdkEventKey ();
1836 OS.memmove (gdkEvent, event, GdkEventKey.sizeof);
1837 return sendKeyEvent (SWT.KeyUp, gdkEvent) ? 0 : 1;
1838}
1839
1840long /*int*/ gtk_leave_notify_event (long /*int*/ widget, long /*int*/ event) {
1841 display.removeMouseHoverTimeout (handle);
1842 GdkEventCrossing gdkEvent = new GdkEventCrossing ();
1843 OS.memmove (gdkEvent, event, GdkEventCrossing.sizeof);
1844 if (gdkEvent.mode != OS.GDK_CROSSING_NORMAL) return 0;
1845 if (gdkEvent.subwindow != 0) return 0;
1846 sendMouseEvent (SWT.MouseExit, 0, event);
1847 return 0;
1848}
1849
1850long /*int*/ gtk_mnemonic_activate (long /*int*/ widget, long /*int*/ arg1) {
1851 int result = 0;
1852 long /*int*/ eventPtr = OS.gtk_get_current_event ();
1853 if (eventPtr != 0) {
1854 GdkEventKey keyEvent = new GdkEventKey ();
1855 OS.memmove (keyEvent, eventPtr, GdkEventKey.sizeof);
1856 if (keyEvent.type == OS.GDK_KEY_PRESS) {
1857 Control focusControl = display.getFocusControl ();
1858 long /*int*/ focusHandle = focusControl != null ? focusControl.focusHandle () : 0;
1859 if (focusHandle != 0) {
1860 display.mnemonicControl = this;
1861 OS.gtk_widget_event (focusHandle, eventPtr);
1862 display.mnemonicControl = null;
1863 }
1864 result = 1;
1865 }
1866 OS.gdk_event_free (eventPtr);
1867 }
1868 return result;
1869}
1870
1871long /*int*/ gtk_motion_notify_event (long /*int*/ widget, long /*int*/ event) {
1872 if (hooks (SWT.DragDetect)) {
1873 if (!display.dragging) {
1874 int [] state = new int [1];
1875 OS.gdk_event_get_state (event, state);
1876 if ((state [0] & OS.GDK_BUTTON1_MASK) != 0) {
1877 double [] px = new double [1], py = new double [1];
1878 OS.gdk_event_get_coords (event, px, py);
1879 if (OS.gtk_drag_check_threshold (handle, display.dragStartX, display.dragStartY, (int) px [0], (int) py [0])){
1880 display.dragging = true;
1881 Event e = new Event ();
1882 e.x = display.dragStartX;
1883 e.y = display.dragStartY;
1884 postEvent (SWT.DragDetect, e);
1885 }
1886 }
1887 }
1888 }
1889 if (hooks (SWT.MouseHover) || filters (SWT.MouseHover)) {
1890 display.addMouseHoverTimeout (handle);
1891 }
1892 sendMouseEvent (SWT.MouseMove, 0, event);
1893 return 0;
1894}
1895
1896long /*int*/ gtk_popup_menu (long /*int*/ widget) {
1897 if (!hasFocus()) return 0;
1898 int [] x = new int [1], y = new int [1];
1899 OS.gdk_window_get_pointer (0, x, y, null);
1900 showMenu (x [0], y [0]);
1901 return 0;
1902}
1903
1904long /*int*/ gtk_preedit_changed (long /*int*/ imcontext) {
1905 display.showIMWindow (this);
1906 return 0;
1907}
1908
1909long /*int*/ gtk_realize (long /*int*/ widget) {
1910 long /*int*/ imHandle = imHandle ();
1911 if (imHandle != 0) {
1912 long /*int*/ window = OS.GTK_WIDGET_WINDOW (paintHandle ());
1913 OS.gtk_im_context_set_client_window (imHandle, window);
1914 }
1915 return 0;
1916}
1917
1918long /*int*/ gtk_show_help (long /*int*/ widget, long /*int*/ helpType) {
1919 if (!hasFocus ()) return 0;
1920 return sendHelpEvent (helpType) ? 1 : 0;
1921}
1922
1923long /*int*/ gtk_unrealize (long /*int*/ widget) {
1924 long /*int*/ imHandle = imHandle ();
1925 if (imHandle != 0) OS.gtk_im_context_set_client_window (imHandle, 0);
1926 return 0;
1927}
1928
1929long /*int*/ gtk_visibility_notify_event (long /*int*/ widget, long /*int*/ event) {
1930 GdkEventVisibility gdkEvent = new GdkEventVisibility ();
1931 OS.memmove (gdkEvent, event, GdkEventVisibility.sizeof);
1932 if (gdkEvent.state == OS.GDK_VISIBILITY_FULLY_OBSCURED) {
1933 state |= OBSCURED;
1934 } else {
1935 if ((state & OBSCURED) != 0) {
1936 long /*int*/ paintHandle = paintHandle ();
1937 int width = OS.GTK_WIDGET_WIDTH (paintHandle);
1938 int height = OS.GTK_WIDGET_HEIGHT (paintHandle);
1939 redrawWidget (0, 0, width, height, false);
1940 }
1941 state &= ~OBSCURED;
1942 }
1943 return 0;
1944}
1945
1946/**
1947 * Invokes platform specific functionality to allocate a new GC handle.
1948 * <p>
1949 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
1950 * API for <code>Control</code>. It is marked public only so that it
1951 * can be shared within the packages provided by SWT. It is not
1952 * available on all platforms, and should never be called from
1953 * application code.
1954 * </p>
1955 *
1956 * @param data the platform specific GC data
1957 * @return the platform specific GC handle
1958 */
1959public long /*int*/ internal_new_GC (GCData data) {
1960 checkWidget ();
1961 long /*int*/ window = paintWindow ();
1962 if (window == 0) SWT.error (SWT.ERROR_NO_HANDLES);
1963 long /*int*/ gdkGC = OS.gdk_gc_new (window);
1964 if (gdkGC == 0) error (SWT.ERROR_NO_HANDLES);
1965 if (data != null) {
1966 int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
1967 if ((data.style & mask) == 0) {
1968 data.style |= style & (mask | SWT.MIRRORED);
1969 }
1970 data.drawable = window;
1971 data.device = display;
1972 data.background = getBackgroundColor ();
1973 data.foreground = getForegroundColor ();
1974 data.font = font != null ? font.handle : defaultFont ();
1975 }
1976 return gdkGC;
1977}
1978
1979long /*int*/ imHandle () {
1980 return 0;
1981}
1982
1983/**
1984 * Invokes platform specific functionality to dispose a GC handle.
1985 * <p>
1986 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
1987 * API for <code>Control</code>. It is marked public only so that it
1988 * can be shared within the packages provided by SWT. It is not
1989 * available on all platforms, and should never be called from
1990 * application code.
1991 * </p>
1992 *
1993 * @param hDC the platform specific GC handle
1994 * @param data the platform specific GC data
1995 */
1996public void internal_dispose_GC (long /*int*/ gdkGC, GCData data) {
1997 checkWidget ();
1998 OS.g_object_unref (gdkGC);
1999}
2000
2001/**
2002 * Returns <code>true</code> if the underlying operating
2003 * system supports this reparenting, otherwise <code>false</code>
2004 *
2005 * @return <code>true</code> if the widget can be reparented, otherwise <code>false</code>
2006 *
2007 * @exception SWTException <ul>
2008 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2009 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2010 * </ul>
2011 */
2012public boolean isReparentable () {
2013 checkWidget();
2014 return true;
2015}
2016boolean isShowing () {
2017 /*
2018 * This is not complete. Need to check if the
2019 * widget is obscurred by a parent or sibling.
2020 */
2021 if (!isVisible ()) return false;
2022 Control control = this;
2023 while (control != null) {
2024 Point size = control.getSize ();
2025 if (size.x == 1 || size.y == 1) {
2026 return false;
2027 }
2028 control = control.parent;
2029 }
2030 return true;
2031}
2032boolean isTabGroup () {
2033 Control [] tabList = parent._getTabList ();
2034 if (tabList != null) {
2035 for (int i=0; i<tabList.length; i++) {
2036 if (tabList [i] == this) return true;
2037 }
2038 }
2039 int code = traversalCode (0, null);
2040 if ((code & (SWT.TRAVERSE_ARROW_PREVIOUS | SWT.TRAVERSE_ARROW_NEXT)) != 0) return false;
2041 return (code & (SWT.TRAVERSE_TAB_PREVIOUS | SWT.TRAVERSE_TAB_NEXT)) != 0;
2042}
2043boolean isTabItem () {
2044 Control [] tabList = parent._getTabList ();
2045 if (tabList != null) {
2046 for (int i=0; i<tabList.length; i++) {
2047 if (tabList [i] == this) return false;
2048 }
2049 }
2050 int code = traversalCode (0, null);
2051 return (code & (SWT.TRAVERSE_ARROW_PREVIOUS | SWT.TRAVERSE_ARROW_NEXT)) != 0;
2052}
2053
2054/**
2055 * Returns <code>true</code> if the receiver is enabled and all
2056 * of the receiver's ancestors are enabled, and <code>false</code>
2057 * otherwise. A disabled control is typically not selectable from the
2058 * user interface and draws with an inactive or "grayed" look.
2059 *
2060 * @return the receiver's enabled state
2061 *
2062 * @exception SWTException <ul>
2063 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2064 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2065 * </ul>
2066 *
2067 * @see #getEnabled
2068 */
2069public boolean isEnabled () {
2070 checkWidget ();
2071 return getEnabled () && parent.isEnabled ();
2072}
2073
2074boolean isFocusAncestor (Control control) {
2075 while (control != null && control != this) {
2076 control = control.parent;
2077 }
2078 return control == this;
2079}
2080
2081/**
2082 * Returns <code>true</code> if the receiver has the user-interface
2083 * focus, and <code>false</code> otherwise.
2084 *
2085 * @return the receiver's focus state
2086 *
2087 * @exception SWTException <ul>
2088 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2089 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2090 * </ul>
2091 */
2092public boolean isFocusControl () {
2093 checkWidget();
2094 return hasFocus ();
2095}
2096
2097/**
2098 * Returns <code>true</code> if the receiver is visible and all
2099 * of the receiver's ancestors are visible and <code>false</code>
2100 * otherwise.
2101 *
2102 * @return the receiver's visibility state
2103 *
2104 * @exception SWTException <ul>
2105 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2106 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2107 * </ul>
2108 *
2109 * @see #getVisible
2110 */
2111public boolean isVisible () {
2112 checkWidget();
2113 return getVisible () && parent.isVisible ();
2114}
2115
2116Decorations menuShell () {
2117 return parent.menuShell ();
2118}
2119
2120boolean mnemonicHit (char key) {
2121 return false;
2122}
2123
2124boolean mnemonicMatch (char key) {
2125 return false;
2126}
2127
2128void register () {
2129 super.register ();
2130 if (fixedHandle != 0) display.addWidget (fixedHandle, this);
2131 long /*int*/ imHandle = imHandle ();
2132 if (imHandle != 0) display.addWidget (imHandle, this);
2133}
2134
2135/**
2136 * Causes the entire bounds of the receiver to be marked
2137 * as needing to be redrawn. The next time a paint request
2138 * is processed, the control will be completely painted,
2139 * including the background.
2140 *
2141 * @exception SWTException <ul>
2142 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2143 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2144 * </ul>
2145 *
2146 * @see #update
2147 * @see PaintListener
2148 * @see SWT#Paint
2149 * @see SWT#NO_BACKGROUND
2150 * @see SWT#NO_REDRAW_RESIZE
2151 * @see SWT#NO_MERGE_PAINTS
2152 */
2153public void redraw () {
2154 checkWidget();
2155 long /*int*/ paintHandle = paintHandle ();
2156 int width = OS.GTK_WIDGET_WIDTH (paintHandle);
2157 int height = OS.GTK_WIDGET_HEIGHT (paintHandle);
2158 redrawWidget (0, 0, width, height, true);
2159}
2160/**
2161 * Causes the rectangular area of the receiver specified by
2162 * the arguments to be marked as needing to be redrawn.
2163 * The next time a paint request is processed, that area of
2164 * the receiver will be painted, including the background.
2165 * If the <code>all</code> flag is <code>true</code>, any
2166 * children of the receiver which intersect with the specified
2167 * area will also paint their intersecting areas. If the
2168 * <code>all</code> flag is <code>false</code>, the children
2169 * will not be painted.
2170 *
2171 * @param x the x coordinate of the area to draw
2172 * @param y the y coordinate of the area to draw
2173 * @param width the width of the area to draw
2174 * @param height the height of the area to draw
2175 * @param all <code>true</code> if children should redraw, and <code>false</code> otherwise
2176 *
2177 * @exception SWTException <ul>
2178 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2179 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2180 * </ul>
2181 *
2182 * @see #update
2183 * @see PaintListener
2184 * @see SWT#Paint
2185 * @see SWT#NO_BACKGROUND
2186 * @see SWT#NO_REDRAW_RESIZE
2187 * @see SWT#NO_MERGE_PAINTS
2188 */
2189public void redraw (int x, int y, int width, int height, boolean all) {
2190 checkWidget();
2191 redrawWidget (x, y, width, height, all);
2192}
2193
2194void redrawWidget (int x, int y, int width, int height, boolean all) {
2195 if ((OS.GTK_WIDGET_FLAGS (handle) & OS.GTK_REALIZED) == 0) return;
2196 long /*int*/ window = paintWindow ();
2197 GdkRectangle rect = new GdkRectangle ();
2198 rect.x = x;
2199 rect.y = y;
2200 rect.width = width;
2201 rect.height = height;
2202 OS.gdk_window_invalidate_rect (window, rect, all);
2203}
2204
2205void releaseChild () {
2206 parent.removeControl (this);
2207}
2208
2209void releaseHandle () {
2210 super.releaseHandle ();
2211 fixedHandle = 0;
2212}
2213
2214void releaseWidget () {
2215 display.removeMouseHoverTimeout (handle);
2216 super.releaseWidget ();
2217 long /*int*/ imHandle = imHandle ();
2218 if (imHandle != 0) {
2219 OS.gtk_im_context_reset (imHandle);
2220 OS.gtk_im_context_set_client_window (imHandle, 0);
2221 }
2222 if (enableWindow != 0) {
2223 OS.gdk_window_set_user_data (enableWindow, 0);
2224 OS.gdk_window_destroy (enableWindow);
2225 enableWindow = 0;
2226 }
2227 if (menu != null && !menu.isDisposed ()) {
2228 menu.dispose ();
2229 }
2230 menu = null;
2231 cursor = null;
2232 toolTipText = null;
2233 parent = null;
2234 layoutData = null;
2235 accessible = null;
2236}
2237
2238void sendFocusEvent (int type) {
2239 Shell shell = _getShell ();
2240 sendEvent (type);
2241 switch (type) {
2242 case SWT.FocusIn: {
2243 /*
2244 * It is possible that the shell may be
2245 * disposed at this point. If this happens
2246 * don't send the activate and deactivate
2247 * events.
2248 */
2249 if (!shell.isDisposed ()) {
2250 shell.setActiveControl (this);
2251 }
2252 break;
2253 }
2254 case SWT.FocusOut: {
2255 /*
2256 * It is possible that the shell may be
2257 * disposed at this point. If this happens
2258 * don't send the activate and deactivate
2259 * events.
2260 */
2261 if (!shell.isDisposed ()) {
2262 Display display = shell.display;
2263 Control control = display.getFocusControl ();
2264 if (control == null || shell != control.getShell () ) {
2265 shell.setActiveControl (null);
2266 }
2267 }
2268 break;
2269 }
2270 }
2271}
2272
2273boolean sendHelpEvent (long /*int*/ helpType) {
2274 Control control = this;
2275 while (control != null) {
2276 if (control.hooks (SWT.Help)) {
2277 control.postEvent (SWT.Help);
2278 return true;
2279 }
2280 control = control.parent;
2281 }
2282 return false;
2283}
2284
2285char [] sendIMKeyEvent (int type, GdkEventKey keyEvent, char [] chars) {
2286 int index = 0, count = 0, state = 0, time = 0;
2287 if (keyEvent == null) {
2288 long /*int*/ ptr = OS.gtk_get_current_event ();
2289 if (ptr != 0) {
2290 keyEvent = new GdkEventKey ();
2291 OS.memmove (keyEvent, ptr, GdkEventKey.sizeof);
2292 OS.gdk_event_free (ptr);
2293 switch (keyEvent.type) {
2294 case OS.GDK_KEY_PRESS:
2295 case OS.GDK_KEY_RELEASE:
2296 state = keyEvent.state;
2297 time = keyEvent.time;
2298 break;
2299 default:
2300 keyEvent = null;
2301 break;
2302 }
2303 }
2304 }
2305 if (keyEvent == null) {
2306 int [] buffer = new int [1];
2307 OS.gtk_get_current_event_state (buffer);
2308 state = buffer [0];
2309 time = OS.gtk_get_current_event_time();
2310 }
2311 while (index < chars.length) {
2312 Event event = new Event ();
2313 event.time = time;
2314 if (keyEvent != null && keyEvent.length <= 1) {
2315 setKeyState (event, keyEvent);
2316 } else {
2317 setInputState (event, state);
2318 }
2319 event.character = chars [index];
2320 sendEvent (type, event);
2321
2322 /*
2323 * It is possible (but unlikely), that application
2324 * code could have disposed the widget in the key
2325 * events. If this happens, end the processing of
2326 * the key by returning null.
2327 */
2328 if (isDisposed ()) return null;
2329 if (event.doit) chars [count++] = chars [index];
2330 index++;
2331 }
2332 if (count == 0) return null;
2333 if (index != count) {
2334 char [] result = new char [count];
2335 System.arraycopy (chars, 0, result, 0, count);
2336 return result;
2337 }
2338 return chars;
2339}
2340
2341boolean sendKeyEvent (int type, GdkEventKey keyEvent) {
2342 int length = keyEvent.length;
2343 if (length <= 1) {
2344 Event event = new Event ();
2345 event.time = keyEvent.time;
2346 if (!setKeyState (event, keyEvent)) return true;
2347 sendEvent (type, event);
2348 // widget could be disposed at this point
2349
2350 /*
2351 * It is possible (but unlikely), that application
2352 * code could have disposed the widget in the key
2353 * events. If this happens, end the processing of
2354 * the key by returning false.
2355 */
2356 if (isDisposed ()) return false;
2357 return event.doit;
2358 }
2359 byte [] buffer = new byte [length];
2360 OS.memmove (buffer, keyEvent.string, length);
2361 char [] chars = Converter.mbcsToWcs (null, buffer);
2362 return sendIMKeyEvent (type, keyEvent, chars) != null;
2363}
2364
2365void sendMouseEvent (int type, int button, long /*int*/ eventPtr) {
2366 Event event = new Event ();
2367 event.time = OS.gdk_event_get_time (eventPtr);
2368 event.button = button;
2369 if (type == SWT.MouseMove) {
2370 GdkEventMotion gdkEvent = new GdkEventMotion ();
2371 OS.memmove (gdkEvent, eventPtr, GdkEventMotion.sizeof);
2372 if (gdkEvent.is_hint != 0) {
2373 int [] pointer_x = new int [1], pointer_y = new int [1];
2374 OS.gdk_window_get_pointer (gdkEvent.window, pointer_x, pointer_y, null);
2375 event.x = pointer_x [0];
2376 event.y = pointer_y [0];
2377 } else {
2378 int [] origin_x = new int [1], origin_y = new int [1];
2379 OS.gdk_window_get_origin (gdkEvent.window, origin_x, origin_y);
2380 event.x = (int) (gdkEvent.x_root - origin_x [0]);
2381 event.y = (int) (gdkEvent.y_root - origin_y [0]);
2382 }
2383 } else {
2384 double [] root_x = new double [1], root_y = new double [1];
2385 OS.gdk_event_get_root_coords (eventPtr, root_x, root_y);
2386 long /*int*/ window = OS.GTK_WIDGET_WINDOW (eventHandle ());
2387 int [] origin_x = new int [1], origin_y = new int [1];
2388 OS.gdk_window_get_origin (window, origin_x, origin_y);
2389 event.x = (int)(root_x [0] - origin_x [0]);
2390 event.y = (int)(root_y [0] - origin_y [0]);
2391 }
2392 int [] state = new int [1];
2393 OS.gdk_event_get_state (eventPtr, state);
2394 setInputState (event, state [0]);
2395 postEvent (type, event);
2396}
2397
2398/**
2399 * Sets the receiver's background color to the color specified
2400 * by the argument, or to the default system color for the control
2401 * if the argument is null.
2402 *
2403 * @param color the new color (or null)
2404 *
2405 * @exception IllegalArgumentException <ul>
2406 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
2407 * </ul>
2408 * @exception SWTException <ul>
2409 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2410 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2411 * </ul>
2412 */
2413public void setBackground (Color color) {
2414 checkWidget();
2415 GdkColor gdkColor = null;
2416 if (color != null) {
2417 if (color.isDisposed ()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
2418 gdkColor = color.handle;
2419 }
2420 boolean set = false;
2421 if (gdkColor == null) {
2422 long /*int*/ style = OS.gtk_widget_get_modifier_style (handle);
2423 set = (OS.gtk_rc_style_get_color_flags (style, OS.GTK_STATE_NORMAL) & OS.GTK_RC_BG) != 0;
2424 } else {
2425 GdkColor oldColor = getBackgroundColor ();
2426 set = oldColor.pixel != gdkColor.pixel;
2427 }
2428 if (set) setBackgroundColor (gdkColor);
2429}
2430
2431void setBackgroundColor (long /*int*/ handle, GdkColor color) {
2432 int index = OS.GTK_STATE_NORMAL;
2433 long /*int*/ style = OS.gtk_widget_get_modifier_style (handle);
2434 long /*int*/ ptr = OS.gtk_rc_style_get_bg_pixmap_name (style, index);
2435 if (ptr != 0) OS.g_free (ptr);
2436 String name = color == null ? "<parent>" : "<none>";
2437 byte[] buffer = Converter.wcsToMbcs (null, name, true);
2438 ptr = OS.g_malloc (buffer.length);
2439 OS.memmove (ptr, buffer, buffer.length);
2440 OS.gtk_rc_style_set_bg_pixmap_name (style, index, ptr);
2441 OS.gtk_rc_style_set_bg (style, index, color);
2442 int flags = OS.gtk_rc_style_get_color_flags (style, index);
2443 flags = (color == null) ? flags & ~OS.GTK_RC_BG : flags | OS.GTK_RC_BG;
2444 OS.gtk_rc_style_set_color_flags (style, index, flags);
2445 OS.gtk_widget_modify_style (handle, style);
2446}
2447void setBackgroundColor (GdkColor color) {
2448 setBackgroundColor(handle, color);
2449}
2450
2451/**
2452 * If the argument is <code>true</code>, causes the receiver to have
2453 * all mouse events delivered to it until the method is called with
2454 * <code>false</code> as the argument.
2455 *
2456 * @param capture <code>true</code> to capture the mouse, and <code>false</code> to release it
2457 *
2458 * @exception SWTException <ul>
2459 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2460 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2461 * </ul>
2462 */
2463public void setCapture (boolean capture) {
2464 checkWidget();
2465 /* FIXME !!!!! */
2466 /*
2467 if (capture) {
2468 OS.gtk_widget_grab_focus (handle);
2469 } else {
2470 OS.gtk_widget_grab_default (handle);
2471 }
2472 */
2473}
2474/**
2475 * Sets the receiver's cursor to the cursor specified by the
2476 * argument, or to the default cursor for that kind of control
2477 * if the argument is null.
2478 * <p>
2479 * When the mouse pointer passes over a control its appearance
2480 * is changed to match the control's cursor.
2481 * </p>
2482 *
2483 * @param cursor the new cursor (or null)
2484 *
2485 * @exception IllegalArgumentException <ul>
2486 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
2487 * </ul>
2488 * @exception SWTException <ul>
2489 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2490 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2491 * </ul>
2492 */
2493public void setCursor (Cursor cursor) {
2494 checkWidget();
2495 if (cursor != null && cursor.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
2496 this.cursor = cursor;
2497 setCursor (cursor != null ? cursor.handle : 0);
2498}
2499
2500void setCursor (long /*int*/ cursor) {
2501 long /*int*/ window = paintWindow ();
2502 if (window != 0) {
2503 OS.gdk_window_set_cursor (window, cursor);
2504 OS.gdk_flush ();
2505 }
2506}
2507
2508/**
2509 * Enables the receiver if the argument is <code>true</code>,
2510 * and disables it otherwise. A disabled control is typically
2511 * not selectable from the user interface and draws with an
2512 * inactive or "grayed" look.
2513 *
2514 * @param enabled the new enabled state
2515 *
2516 * @exception SWTException <ul>
2517 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2518 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2519 * </ul>
2520 */
2521public void setEnabled (boolean enabled) {
2522 checkWidget();
2523 if (((state & DISABLED) == 0) == enabled) return;
2524 Control control = null;
2525 boolean fixFocus = false;
2526 if (!enabled) {
2527 control = display.getFocusControl ();
2528 fixFocus = isFocusAncestor (control);
2529 }
2530 if (enabled) {
2531 state &= ~DISABLED;
2532 } else {
2533 state |= DISABLED;
2534 }
2535 enableWidget (enabled);
2536 if (enabled) {
2537 if (enableWindow != 0) {
2538 OS.gdk_window_set_user_data (enableWindow, 0);
2539 OS.gdk_window_destroy (enableWindow);
2540 enableWindow = 0;
2541 }
2542 } else {
2543 OS.gtk_widget_realize (handle);
2544 long /*int*/ parentHandle = parent.parentingHandle ();
2545 long /*int*/ window = OS.GTK_WIDGET_WINDOW (parentHandle);
2546 Rectangle rect = getBounds ();
2547 GdkWindowAttr attributes = new GdkWindowAttr ();
2548 attributes.x = rect.x;
2549 attributes.y = rect.y;
2550 attributes.width = rect.width;
2551 attributes.height = rect.height;
2552 attributes.event_mask = (0xFFFFFFFF & ~OS.ExposureMask);
2553 attributes.wclass = OS.GDK_INPUT_ONLY;
2554 attributes.window_type = OS.GDK_WINDOW_CHILD;
2555 enableWindow = OS.gdk_window_new (window, attributes, OS.GDK_WA_X | OS.GDK_WA_Y);
2556 if (enableWindow != 0) {
2557 long /*int*/ topHandle = topHandle ();
2558 OS.gdk_window_set_user_data (enableWindow, parentHandle);
2559 if (!OS.GDK_WINDOWING_X11 ()) {
2560 OS.gdk_window_raise (enableWindow);
2561 } else {
2562 long /*int*/ topWindow = OS.GTK_WIDGET_WINDOW (topHandle);
2563 long /*int*/ xDisplay = OS.gdk_x11_drawable_get_xdisplay (topWindow);
2564 long /*int*/ xWindow = OS.gdk_x11_drawable_get_xid (enableWindow);
2565 int xScreen = OS.XDefaultScreen (xDisplay);
2566 int flags = OS.CWStackMode | OS.CWSibling;
2567 XWindowChanges changes = new XWindowChanges ();
2568 changes.sibling = OS.gdk_x11_drawable_get_xid (topWindow);
2569 changes.stack_mode = OS.Above;
2570 OS.XReconfigureWMWindow (xDisplay, xWindow, xScreen, flags, changes);
2571 }
2572 if (OS.GTK_WIDGET_VISIBLE (topHandle)) OS.gdk_window_show (enableWindow);
2573 }
2574 }
2575 if (fixFocus) fixFocus (control);
2576}
2577
2578/**
2579 * Causes the receiver to have the <em>keyboard focus</em>,
2580 * such that all keyboard events will be delivered to it. Focus
2581 * reassignment will respect applicable platform constraints.
2582 *
2583 * @return <code>true</code> if the control got focus, and <code>false</code> if it was unable to.
2584 *
2585 * @exception SWTException <ul>
2586 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2587 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2588 * </ul>
2589 *
2590 * @see #forceFocus
2591 */
2592public boolean setFocus () {
2593 checkWidget();
2594 if ((style & SWT.NO_FOCUS) != 0) return false;
2595 return forceFocus ();
2596}
2597
2598/**
2599 * Sets the font that the receiver will use to paint textual information
2600 * to the font specified by the argument, or to the default font for that
2601 * kind of control if the argument is null.
2602 *
2603 * @param font the new font (or null)
2604 *
2605 * @exception IllegalArgumentException <ul>
2606 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
2607 * </ul>
2608 * @exception SWTException <ul>
2609 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2610 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2611 * </ul>
2612 */
2613public void setFont (Font font) {
2614 checkWidget();
2615 this.font = font;
2616 long /*int*/ fontDesc;
2617 if (font == null) {
2618 fontDesc = defaultFont ();
2619 } else {
2620 if (font.isDisposed ()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
2621 fontDesc = font.handle;
2622 }
2623 setFontDescription (fontDesc);
2624}
2625
2626void setFontDescription (long /*int*/ font) {
2627 OS.gtk_widget_modify_font (handle, font);
2628}
2629
2630/**
2631 * Sets the receiver's foreground color to the color specified
2632 * by the argument, or to the default system color for the control
2633 * if the argument is null.
2634 *
2635 * @param color the new color (or null)
2636 *
2637 * @exception IllegalArgumentException <ul>
2638 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
2639 * </ul>
2640 * @exception SWTException <ul>
2641 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2642 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2643 * </ul>
2644 */
2645public void setForeground (Color color) {
2646 checkWidget();
2647 GdkColor gdkColor = null;
2648 if (color != null) {
2649 if (color.isDisposed ()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
2650 gdkColor = color.handle;
2651 }
2652 boolean set = false;
2653 if (gdkColor == null) {
2654 long /*int*/ style = OS.gtk_widget_get_modifier_style (handle);
2655 set = (OS.gtk_rc_style_get_color_flags (style, OS.GTK_STATE_NORMAL) & OS.GTK_RC_FG) != 0;
2656 } else {
2657 GdkColor oldColor = getForegroundColor ();
2658 set = oldColor.pixel != gdkColor.pixel;
2659 }
2660 if (set) setForegroundColor (gdkColor);
2661}
2662
2663void setForegroundColor (GdkColor color) {
2664 OS.gtk_widget_modify_fg (handle, OS.GTK_STATE_NORMAL, color);
2665}
2666
2667void setInitialSize () {
2668 resizeHandle (1, 1);
2669 /*
2670 * Force the container to allocate the size of its children.
2671 */
2672 long /*int*/ parentHandle = parent.parentingHandle ();
2673 OS.gtk_container_resize_children (parentHandle);
2674}
2675
2676/**
2677 * Sets the receiver's pop up menu to the argument.
2678 * All controls may optionally have a pop up
2679 * menu that is displayed when the user requests one for
2680 * the control. The sequence of key strokes, button presses
2681 * and/or button releases that are used to request a pop up
2682 * menu is platform specific.
2683 *
2684 * @param menu the new pop up menu
2685 *
2686 * @exception IllegalArgumentException <ul>
2687 * <li>ERROR_MENU_NOT_POP_UP - the menu is not a pop up menu</li>
2688 * <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</li>
2689 * <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</li>
2690 * </ul>
2691 * @exception SWTException <ul>
2692 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2693 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2694 * </ul>
2695 */
2696public void setMenu (Menu menu) {
2697 checkWidget();
2698 if (menu != null) {
2699 if ((menu.style & SWT.POP_UP) == 0) {
2700 error (SWT.ERROR_MENU_NOT_POP_UP);
2701 }
2702 if (menu.parent != menuShell ()) {
2703 error (SWT.ERROR_INVALID_PARENT);
2704 }
2705 }
2706 this.menu = menu;
2707}
2708
2709/**
2710 * Changes the parent of the widget to be the one provided if
2711 * the underlying operating system supports this feature.
2712 * Answers <code>true</code> if the parent is successfully changed.
2713 *
2714 * @param parent the new parent for the control.
2715 * @return <code>true</code> if the parent is changed and <code>false</code> otherwise.
2716 *
2717 * @exception IllegalArgumentException <ul>
2718 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
2719 * </ul>
2720 * @exception SWTError <ul>
2721 * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
2722 * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
2723 * </ul>
2724 */
2725public boolean setParent (Composite parent) {
2726 checkWidget ();
2727 if (parent == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
2728 if (parent.isDisposed()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
2729 if (this.parent == parent) return true;
2730 if (!isReparentable ()) return false;
2731 releaseChild ();
2732 Shell newShell = parent.getShell (), oldShell = getShell ();
2733 Decorations newDecorations = parent.menuShell (), oldDecorations = menuShell ();
2734 Menu [] menus = oldShell.findMenus (this);
2735 if (oldShell != newShell || oldDecorations != newDecorations) {
2736 fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
2737 newDecorations.fixAccelGroup ();
2738 oldDecorations.fixAccelGroup ();
2739 }
2740 long /*int*/ topHandle = topHandle ();
2741 long /*int*/ newParent = parent.parentingHandle();
2742 int x = OS.GTK_WIDGET_X (topHandle);
2743 int y = OS.GTK_WIDGET_Y (topHandle);
2744 OS.gtk_widget_reparent (topHandle, newParent);
2745 OS.gtk_fixed_move (newParent, topHandle, x, y);
2746 this.parent = parent;
2747 setZOrder (null, false);
2748 return true;
2749}
2750
2751boolean setRadioSelection (boolean value) {
2752 return false;
2753}
2754
2755/**
2756 * If the argument is <code>false</code>, causes subsequent drawing
2757 * operations in the receiver to be ignored. No drawing of any kind
2758 * can occur in the receiver until the flag is set to true.
2759 * Graphics operations that occurred while the flag was
2760 * <code>false</code> are lost. When the flag is set to <code>true</code>,
2761 * the entire widget is marked as needing to be redrawn.
2762 * <p>
2763 * Note: This operation is a hint and may not be supported on some
2764 * platforms or for some widgets.
2765 * </p>
2766 *
2767 * @param redraw the new redraw state
2768 *
2769 * @exception SWTException <ul>
2770 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2771 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2772 * </ul>
2773 *
2774 * @see #redraw
2775 * @see #update
2776 */
2777public void setRedraw (boolean redraw) {
2778 checkWidget();
2779 if (redraw) {
2780 if (--drawCount == 0) {
2781 if (redrawWindow != 0) {
2782 long /*int*/ window = paintWindow ();
2783 OS.gdk_window_destroy (redrawWindow);
2784 OS.gdk_window_set_events (window, OS.gtk_widget_get_events (paintHandle ()));
2785 redrawWindow = 0;
2786 }
2787 }
2788 } else {
2789 if (drawCount++ == 0) {
2790 if ((OS.GTK_WIDGET_FLAGS (handle) & OS.GTK_REALIZED) != 0) {
2791 long /*int*/ window = paintWindow ();
2792 Rectangle rect = getBounds ();
2793 GdkWindowAttr attributes = new GdkWindowAttr ();
2794 attributes.width = rect.width;
2795 attributes.height = rect.height;
2796 attributes.event_mask = OS.GDK_EXPOSURE_MASK;
2797 attributes.window_type = OS.GDK_WINDOW_CHILD;
2798 redrawWindow = OS.gdk_window_new (window, attributes, 0);
2799 if (redrawWindow != 0) {
2800 int mouseMask = OS.GDK_BUTTON_PRESS_MASK | OS.GDK_BUTTON_RELEASE_MASK |
2801 OS.GDK_ENTER_NOTIFY_MASK | OS.GDK_LEAVE_NOTIFY_MASK |
2802 OS.GDK_POINTER_MOTION_MASK | OS.GDK_POINTER_MOTION_HINT_MASK |
2803 OS.GDK_BUTTON_MOTION_MASK | OS.GDK_BUTTON1_MOTION_MASK |
2804 OS.GDK_BUTTON2_MOTION_MASK | OS.GDK_BUTTON3_MOTION_MASK;
2805 OS.gdk_window_set_events (window, OS.gdk_window_get_events (window) & ~mouseMask);
2806 OS.gdk_window_set_back_pixmap (redrawWindow, 0, false);
2807 OS.gdk_window_raise (redrawWindow);
2808 OS.gdk_window_show (redrawWindow);
2809 }
2810 }
2811 }
2812 }
2813}
2814
2815boolean setTabGroupFocus (boolean next) {
2816 return setTabItemFocus (next);
2817}
2818boolean setTabItemFocus (boolean next) {
2819 if (!isShowing ()) return false;
2820 return forceFocus ();
2821}
2822
2823/**
2824 * Sets the receiver's tool tip text to the argument, which
2825 * may be null indicating that no tool tip text should be shown.
2826 *
2827 * @param string the new tool tip text (or null)
2828 *
2829 * @exception SWTException <ul>
2830 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2831 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2832 * </ul>
2833 */
2834public void setToolTipText (String string) {
2835 checkWidget();
2836 Shell shell = _getShell ();
2837 shell.setToolTipText (eventHandle (), toolTipText = string);
2838}
2839
2840/**
2841 * Marks the receiver as visible if the argument is <code>true</code>,
2842 * and marks it invisible otherwise.
2843 * <p>
2844 * If one of the receiver's ancestors is not visible or some
2845 * other condition makes the receiver not visible, marking
2846 * it visible may not actually cause it to be displayed.
2847 * </p>
2848 *
2849 * @param visible the new visibility state
2850 *
2851 * @exception SWTException <ul>
2852 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2853 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2854 * </ul>
2855 */
2856public void setVisible (boolean visible) {
2857 checkWidget();
2858 long /*int*/ topHandle = topHandle();
2859 if ((OS.GTK_WIDGET_VISIBLE (topHandle) == visible)) return;
2860 if (visible) {
2861 /*
2862 * It is possible (but unlikely), that application
2863 * code could have disposed the widget in the show
2864 * event. If this happens, just return.
2865 */
2866 sendEvent (SWT.Show);
2867 if (isDisposed ()) return;
2868 if (enableWindow != 0) OS.gdk_window_show (enableWindow);
2869 OS.gtk_widget_show (topHandle);
2870 } else {
2871 /*
2872 * Bug in GTK. Invoking gtk_widget_hide() on a widget that has
2873 * focus causes a focus_out_event to be sent. If the client disposes
2874 * the widget inside the event, GTK GP's. The fix is to reassign focus
2875 * before hiding the widget.
2876 *
2877 * NOTE: In order to stop the same widget from taking focus,
2878 * temporarily clear and set the GTK_VISIBLE flag.
2879 */
2880 Control control = null;
2881 boolean fixFocus = false;
2882 if (!visible) {
2883 control = display.getFocusControl ();
2884 fixFocus = isFocusAncestor (control);
2885 }
2886 if (fixFocus) {
2887 int flags = OS.GTK_WIDGET_FLAGS (topHandle);
2888 OS.GTK_WIDGET_UNSET_FLAGS (topHandle, OS.GTK_VISIBLE);
2889 fixFocus (control);
2890 if (isDisposed ()) return;
2891 if ((flags & OS.GTK_VISIBLE) != 0) {
2892 OS.GTK_WIDGET_SET_FLAGS (topHandle, OS.GTK_VISIBLE);
2893 }
2894 }
2895 OS.gtk_widget_hide (topHandle);
2896 if (enableWindow != 0) OS.gdk_window_hide (enableWindow);
2897 sendEvent (SWT.Hide);
2898 }
2899}
2900
2901void setZOrder (Control sibling, boolean above) {
2902 setZOrder (sibling, above, true);
2903}
2904
2905void setZOrder (Control sibling, boolean above, boolean fixChildren) {
2906 long /*int*/ topHandle = topHandle ();
2907 long /*int*/ siblingHandle = sibling != null ? sibling.topHandle () : 0;
2908 long /*int*/ window = OS.GTK_WIDGET_WINDOW (topHandle);
2909 if (window != 0) {
2910 long /*int*/ siblingWindow = 0;
2911 if (sibling != null) {
2912 if (above && sibling.enableWindow != 0) {
2913 siblingWindow = enableWindow;
2914 } else {
2915 siblingWindow = OS.GTK_WIDGET_WINDOW (siblingHandle);
2916 }
2917 }
2918 long /*int*/ redrawWindow = fixChildren ? parent.redrawWindow : 0;
2919 if (!OS.GDK_WINDOWING_X11 () || (siblingWindow == 0 && redrawWindow == 0)) {
2920 if (above) {
2921 OS.gdk_window_raise (window);
2922 if (redrawWindow != 0) OS.gdk_window_raise (redrawWindow);
2923 if (enableWindow != 0) OS.gdk_window_raise (enableWindow);
2924 } else {
2925 if (enableWindow != 0) OS.gdk_window_lower (enableWindow);
2926 OS.gdk_window_lower (window);
2927 }
2928 } else {
2929 XWindowChanges changes = new XWindowChanges ();
2930 changes.sibling = OS.gdk_x11_drawable_get_xid (siblingWindow != 0 ? siblingWindow : redrawWindow);
2931 changes.stack_mode = above ? OS.Above : OS.Below;
2932 if (redrawWindow != 0 && siblingWindow == 0) changes.stack_mode = OS.Below;
2933 long /*int*/ xDisplay = OS.gdk_x11_drawable_get_xdisplay (window);
2934 long /*int*/ xWindow = OS.gdk_x11_drawable_get_xid (window);
2935 int xScreen = OS.XDefaultScreen (xDisplay);
2936 int flags = OS.CWStackMode | OS.CWSibling;
2937 /*
2938 * Feature in X. If the receiver is a top level, XConfigureWindow ()
2939 * will fail (with a BadMatch error) for top level shells because top
2940 * level shells are reparented by the window manager and do not share
2941 * the same X window parent. This is the correct behavior but it is
2942 * unexpected. The fix is to use XReconfigureWMWindow () instead.
2943 * When the receiver is not a top level shell, XReconfigureWMWindow ()
2944 * behaves the same as XConfigureWindow ().
2945 */
2946 OS.XReconfigureWMWindow (xDisplay, xWindow, xScreen, flags, changes);
2947 if (enableWindow != 0) {
2948 changes.sibling = OS.gdk_x11_drawable_get_xid (window);
2949 changes.stack_mode = OS.Above;
2950 xWindow = OS.gdk_x11_drawable_get_xid (enableWindow);
2951 OS.XReconfigureWMWindow (xDisplay, xWindow, xScreen, flags, changes);
2952 }
2953 }
2954 }
2955 if (fixChildren) {
2956 if (above) {
2957 parent.moveAbove (topHandle, siblingHandle);
2958 } else {
2959 parent.moveBelow (topHandle, siblingHandle);
2960 }
2961 }
2962 /*
2963 * Make sure that the parent handle is on the bottom of the stack
2964 * when the parent children are siblings of the parent handle.
2965 */
2966 if (!above && fixChildren && parent.parentingHandle () == parent.fixedHandle) {
2967 window = OS.GTK_WIDGET_WINDOW (parent.handle);
2968 if (window != 0) OS.gdk_window_lower (window);
2969 }
2970}
2971
2972boolean showMenu (int x, int y) {
2973 Event event = new Event ();
2974 event.x = x;
2975 event.y = y;
2976 sendEvent (SWT.MenuDetect, event);
2977 if (event.doit) {
2978 if (menu != null && !menu.isDisposed ()) {
2979 menu.createIMMenu (imHandle());
2980 if (event.x != x || event.y != y) {
2981 menu.setLocation (event.x, event.y);
2982 }
2983 menu.setVisible (true);
2984 return true;
2985 }
2986 }
2987 return false;
2988}
2989
2990void sort (int [] items) {
2991 /* Shell Sort from K&R, pg 108 */
2992 int length = items.length;
2993 for (int gap=length/2; gap>0; gap/=2) {
2994 for (int i=gap; i<length; i++) {
2995 for (int j=i-gap; j>=0; j-=gap) {
2996 if (items [j] <= items [j + gap]) {
2997 int swap = items [j];
2998 items [j] = items [j + gap];
2999 items [j + gap] = swap;
3000 }
3001 }
3002 }
3003 }
3004}
3005
3006/**
3007 * Based on the argument, perform one of the expected platform
3008 * traversal action. The argument should be one of the constants:
3009 * <code>SWT.TRAVERSE_ESCAPE</code>, <code>SWT.TRAVERSE_RETURN</code>,
3010 * <code>SWT.TRAVERSE_TAB_NEXT</code>, <code>SWT.TRAVERSE_TAB_PREVIOUS</code>,
3011 * <code>SWT.TRAVERSE_ARROW_NEXT</code> and <code>SWT.TRAVERSE_ARROW_PREVIOUS</code>.
3012 *
3013 * @param traversal the type of traversal
3014 * @return true if the traversal succeeded
3015 *
3016 * @exception SWTException <ul>
3017 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3018 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3019 * </ul>
3020 */
3021public boolean traverse (int traversal) {
3022 checkWidget ();
3023 Event event = new Event ();
3024 event.doit = true;
3025 event.detail = traversal;
3026 return traverse (event);
3027}
3028
3029boolean translateMnemonic (Event event, Control control) {
3030 if (control == this) return false;
3031 if (!isVisible () || !isEnabled ()) return false;
3032 event.doit = this == display.mnemonicControl || mnemonicMatch (event.character);
3033 return traverse (event);
3034}
3035
3036boolean translateMnemonic (int keyval, GdkEventKey gdkEvent) {
3037 int key = OS.gdk_keyval_to_unicode (keyval);
3038 if (key < 0x20) return false;
3039 if (gdkEvent.state == 0) {
3040 int code = traversalCode (keyval, gdkEvent);
3041 if ((code & SWT.TRAVERSE_MNEMONIC) == 0) return false;
3042 } else {
3043 Shell shell = _getShell ();
3044 int mask = OS.GDK_CONTROL_MASK | OS.GDK_SHIFT_MASK | OS.GDK_MOD1_MASK;
3045 if ((gdkEvent.state & mask) != OS.gtk_window_get_mnemonic_modifier (shell.shellHandle)) return false;
3046 }
3047 Decorations shell = menuShell ();
3048 if (shell.isVisible () && shell.isEnabled ()) {
3049 Event event = new Event ();
3050 event.detail = SWT.TRAVERSE_MNEMONIC;
3051 if (setKeyState (event, gdkEvent)) {
3052 return translateMnemonic (event, null) || shell.translateMnemonic (event, this);
3053 }
3054 }
3055 return false;
3056}
3057
3058boolean translateTraversal (GdkEventKey keyEvent) {
3059 int detail = SWT.TRAVERSE_NONE;
3060 int key = keyEvent.keyval;
3061 int code = traversalCode (key, keyEvent);
3062 boolean all = false;
3063 switch (key) {
3064 case OS.GDK_Escape: {
3065 all = true;
3066 detail = SWT.TRAVERSE_ESCAPE;
3067 break;
3068 }
3069 case OS.GDK_KP_Enter:
3070 case OS.GDK_Return: {
3071 all = true;
3072 detail = SWT.TRAVERSE_RETURN;
3073 break;
3074 }
3075 case OS.GDK_ISO_Left_Tab:
3076 case OS.GDK_Tab: {
3077 boolean next = (keyEvent.state & OS.GDK_SHIFT_MASK) == 0;
3078 detail = next ? SWT.TRAVERSE_TAB_NEXT : SWT.TRAVERSE_TAB_PREVIOUS;
3079 break;
3080 }
3081 case OS.GDK_Up:
3082 case OS.GDK_Left:
3083 case OS.GDK_Down:
3084 case OS.GDK_Right: {
3085 boolean next = key == OS.GDK_Down || key == OS.GDK_Right;
3086 detail = next ? SWT.TRAVERSE_ARROW_NEXT : SWT.TRAVERSE_ARROW_PREVIOUS;
3087 break;
3088 }
3089 case OS.GDK_Page_Up:
3090 case OS.GDK_Page_Down: {
3091 all = true;
3092 if ((keyEvent.state & OS.GDK_CONTROL_MASK) == 0) return false;
3093 detail = key == OS.GDK_Page_Down ? SWT.TRAVERSE_PAGE_NEXT : SWT.TRAVERSE_PAGE_PREVIOUS;
3094 break;
3095 }
3096 default:
3097 return false;
3098 }
3099 Event event = new Event ();
3100 event.doit = (code & detail) != 0;
3101 event.detail = detail;
3102 event.time = keyEvent.time;
3103 if (!setKeyState (event, keyEvent)) return false;
3104 Shell shell = getShell ();
3105 Control control = this;
3106 do {
3107 if (control.traverse (event)) return true;
3108 if (!event.doit && control.hooks (SWT.Traverse)) return false;
3109 if (control == shell) return false;
3110 control = control.parent;
3111 } while (all && control != null);
3112 return false;
3113}
3114
3115int traversalCode (int key, GdkEventKey event) {
3116 int code = SWT.TRAVERSE_RETURN | SWT.TRAVERSE_TAB_NEXT | SWT.TRAVERSE_TAB_PREVIOUS | SWT.TRAVERSE_PAGE_NEXT | SWT.TRAVERSE_PAGE_PREVIOUS;
3117 Shell shell = getShell ();
3118 if (shell.parent != null) code |= SWT.TRAVERSE_ESCAPE;
3119 return code;
3120}
3121
3122boolean traverse (Event event) {
3123 /*
3124 * It is possible (but unlikely), that application
3125 * code could have disposed the widget in the traverse
3126 * event. If this happens, return true to stop further
3127 * event processing.
3128 */
3129 sendEvent (SWT.Traverse, event);
3130 if (isDisposed ()) return true;
3131 if (!event.doit) return false;
3132 switch (event.detail) {
3133 case SWT.TRAVERSE_NONE: return true;
3134 case SWT.TRAVERSE_ESCAPE: return traverseEscape ();
3135 case SWT.TRAVERSE_RETURN: return traverseReturn ();
3136 case SWT.TRAVERSE_TAB_NEXT: return traverseGroup (true);
3137 case SWT.TRAVERSE_TAB_PREVIOUS: return traverseGroup (false);
3138 case SWT.TRAVERSE_ARROW_NEXT: return traverseItem (true);
3139 case SWT.TRAVERSE_ARROW_PREVIOUS: return traverseItem (false);
3140 case SWT.TRAVERSE_MNEMONIC: return traverseMnemonic (event.character);
3141 case SWT.TRAVERSE_PAGE_NEXT: return traversePage (true);
3142 case SWT.TRAVERSE_PAGE_PREVIOUS: return traversePage (false);
3143 }
3144 return false;
3145}
3146
3147boolean traverseEscape () {
3148 return false;
3149}
3150
3151boolean traverseGroup (boolean next) {
3152 Control root = computeTabRoot ();
3153 Control group = computeTabGroup ();
3154 Control [] list = root.computeTabList ();
3155 int length = list.length;
3156 int index = 0;
3157 while (index < length) {
3158 if (list [index] == group) break;
3159 index++;
3160 }
3161 /*
3162 * It is possible (but unlikely), that application
3163 * code could have disposed the widget in focus in
3164 * or out events. Ensure that a disposed widget is
3165 * not accessed.
3166 */
3167 if (index == length) return false;
3168 int start = index, offset = (next) ? 1 : -1;
3169 while ((index = ((index + offset + length) % length)) != start) {
3170 Control control = list [index];
3171 if (!control.isDisposed () && control.setTabGroupFocus (next)) {
3172 return true;
3173 }
3174 }
3175 if (group.isDisposed ()) return false;
3176 return group.setTabGroupFocus (next);
3177}
3178
3179boolean traverseItem (boolean next) {
3180 Control [] children = parent._getChildren ();
3181 int length = children.length;
3182 int index = 0;
3183 while (index < length) {
3184 if (children [index] == this) break;
3185 index++;
3186 }
3187 /*
3188 * It is possible (but unlikely), that application
3189 * code could have disposed the widget in focus in
3190 * or out events. Ensure that a disposed widget is
3191 * not accessed.
3192 */
3193 if (index == length) return false;
3194 int start = index, offset = (next) ? 1 : -1;
3195 while ((index = (index + offset + length) % length) != start) {
3196 Control child = children [index];
3197 if (!child.isDisposed () && child.isTabItem ()) {
3198 if (child.setTabItemFocus (next)) return true;
3199 }
3200 }
3201 return false;
3202}
3203
3204boolean traverseReturn () {
3205 return false;
3206}
3207
3208boolean traversePage (boolean next) {
3209 return false;
3210}
3211
3212boolean traverseMnemonic (char key) {
3213 return mnemonicHit (key);
3214}
3215
3216/**
3217 * Forces all outstanding paint requests for the widget
3218 * to be processed before this method returns.
3219 *
3220 * @exception SWTException <ul>
3221 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3222 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3223 * </ul>
3224 *
3225 * @see #redraw
3226 * @see PaintListener
3227 * @see SWT#Paint
3228 */
3229public void update () {
3230 checkWidget ();
3231 update (false);
3232}
3233
3234void update (boolean all) {
3235// checkWidget();
3236 if ((OS.GTK_WIDGET_FLAGS (handle) & OS.GTK_REALIZED) == 0) return;
3237 long /*int*/ window = paintWindow ();
3238 display.flushExposes (window, all);
3239 OS.gdk_window_process_updates (window, all);
3240}
3241}