Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/eclipse/swt/widgets/Composite.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.gtk.*;
16  import org.eclipse.swt.graphics.*;
17  
18  /**
19   * Instances of this class are controls which are capable
20   * of containing other controls.
21   * <dl>
22   * <dt><b>Styles:</b></dt>
23   * <dd>NO_BACKGROUND, NO_FOCUS, NO_MERGE_PAINTS, NO_REDRAW_RESIZE, NO_RADIO_GROUP, EMBEDDED</dd>
24   * <dt><b>Events:</b></dt>
25   * <dd>(none)</dd>
26   * </dl>
27   * <p>
28   * Note: The <code>NO_BACKGROUND</code>, <code>NO_FOCUS</code>, <code>NO_MERGE_PAINTS</code>,
29   * and <code>NO_REDRAW_RESIZE</code> styles are intended for use with <code>Canvas</code>.
30   * They can be used with <code>Composite</code> if you are drawing your own, but their
31   * behavior is undefined if they are used with subclasses of <code>Composite</code> other
32   * than <code>Canvas</code>.
33   * </p><p>
34   * This class may be subclassed by custom control implementors
35   * who are building controls that are constructed from aggregates
36   * of other controls.
37   * </p>
38   *
39   * @see Canvas
40   */
41  public class Composite extends Scrollable {
42    public long /*int*/  embeddedHandle;
43    long /*int*/ imHandle, socketHandle;
44    Layout layout;
45    Control[] tabList;
46  
47  Composite () {
48    /* Do nothing */
49  }
50  
51  /**
52   * Constructs a new instance of this class given its parent
53   * and a style value describing its behavior and appearance.
54   * <p>
55   * The style value is either one of the style constants defined in
56   * class <code>SWT</code> which is applicable to instances of this
57   * class, or must be built by <em>bitwise OR</em>'ing together 
58   * (that is, using the <code>int</code> "|" operator) two or more
59   * of those <code>SWT</code> style constants. The class description
60   * lists the style constants that are applicable to the class.
61   * Style bits are also inherited from superclasses.
62   * </p>
63   *
64   * @param parent a widget which will be the parent of the new instance (cannot be null)
65   * @param style the style of widget to construct
66   *
67   * @exception IllegalArgumentException <ul>
68   *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
69   * </ul>
70   * @exception SWTException <ul>
71   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
72   * </ul>
73   *
74   * @see SWT#NO_BACKGROUND
75   * @see SWT#NO_FOCUS
76   * @see SWT#NO_MERGE_PAINTS
77   * @see SWT#NO_REDRAW_RESIZE
78   * @see SWT#NO_RADIO_GROUP
79   * @see Widget#getStyle
80   */
81  public Composite (Composite parent, int style) {
82    super (parent, style);
83  }
84  
85  Control [] _getChildren () {
86    long /*int*/ parentHandle = parentingHandle ();
87    long /*int*/ list = OS.gtk_container_get_children (parentHandle);
88    if (list == 0) return new Control [0];
89    list = OS.g_list_reverse (list);
90    int count = OS.g_list_length (list);
91    Control [] children = new Control [count];
92    int i = 0, j = 0;
93    while (i < count) {
94      long /*int*/ handle = OS.g_list_nth_data (list, i);
95      if (handle != 0) {
96        Widget widget = display.getWidget (handle);
97        if (widget != null && widget != this) {
98          if (widget instanceof Control) {
99            children [j++] = (Control) widget;
100         }
101       }
102     }
103     i++;
104   }
105   OS.g_list_free (list);
106   if (i == j) return children;
107   Control [] newChildren = new Control [j];
108   System.arraycopy (children, 0, newChildren, 0, j);
109   return newChildren;
110 }
111 
112 Control [] _getTabList () {
113   if (tabList == null) return tabList;
114   int count = 0;
115   for (int i=0; i<tabList.length; i++) {
116     if (!tabList [i].isDisposed ()) count++;
117   }
118   if (count == tabList.length) return tabList;
119   Control [] newList = new Control [count];
120   int index = 0;
121   for (int i=0; i<tabList.length; i++) {
122     if (!tabList [i].isDisposed ()) {
123       newList [index++] = tabList [i];
124     }
125   }
126   tabList = newList;
127   return tabList;
128 }
129 
130 protected void checkSubclass () {
131   /* Do nothing - Subclassing is allowed */
132 }
133 
134 public Point computeSize (int wHint, int hHint, boolean changed) {
135   checkWidget ();
136   if (wHint != SWT.DEFAULT && wHint < 0) wHint = 0;
137   if (hHint != SWT.DEFAULT && hHint < 0) hHint = 0;
138   Point size;
139   if (layout != null) {
140     if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
141       size = layout.computeSize (this, wHint, hHint, changed);
142     } else {
143       size = new Point (wHint, hHint);
144     }
145   } else {
146     size = minimumSize ();
147   }
148   if (size.x == 0) size.x = DEFAULT_WIDTH;
149   if (size.y == 0) size.y = DEFAULT_HEIGHT;
150   if (wHint != SWT.DEFAULT) size.x = wHint;
151   if (hHint != SWT.DEFAULT) size.y = hHint;
152   Rectangle trim = computeTrim (0, 0, size.x, size.y);
153   return new Point (trim.width, trim.height);
154 }
155 
156 Control [] computeTabList () {
157   Control result [] = super.computeTabList ();
158   if (result.length == 0) return result;
159   Control [] list = tabList != null ? _getTabList () : _getChildren ();
160   for (int i=0; i<list.length; i++) {
161     Control child = list [i];
162     Control [] childList = child.computeTabList ();
163     if (childList.length != 0) {
164       Control [] newResult = new Control [result.length + childList.length];
165       System.arraycopy (result, 0, newResult, 0, result.length);
166       System.arraycopy (childList, 0, newResult, result.length, childList.length);
167       result = newResult;
168     }
169   }
170   return result;
171 }
172 
173 void createHandle (int index) {
174   state |= HANDLE | CANVAS;
175   boolean scrolled = (style & (SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER)) != 0;
176   createHandle (index, parent.parentingHandle (), scrolled);
177 }
178 
179 void createHandle (int index, long /*int*/ parentHandle, boolean scrolled) {
180   if (scrolled) {
181     fixedHandle = OS.gtk_fixed_new ();
182     if (fixedHandle == 0) error (SWT.ERROR_NO_HANDLES);
183     OS.gtk_fixed_set_has_window (fixedHandle, true);
184     long /*int*/ vadj = OS.gtk_adjustment_new (0, 0, 100, 1, 10, 10);
185     if (vadj == 0) error (SWT.ERROR_NO_HANDLES);
186     long /*int*/ hadj = OS.gtk_adjustment_new (0, 0, 100, 1, 10, 10);
187     if (hadj == 0) error (SWT.ERROR_NO_HANDLES);
188     scrolledHandle = OS.gtk_scrolled_window_new (hadj, vadj);
189     if (scrolledHandle == 0) SWT.error (SWT.ERROR_NO_HANDLES);
190   }
191   handle = OS.gtk_fixed_new ();
192   if (handle == 0) SWT.error (SWT.ERROR_NO_HANDLES);
193   OS.gtk_fixed_set_has_window (handle, true);
194   OS.GTK_WIDGET_SET_FLAGS(handle, OS.GTK_CAN_FOCUS);
195   if ((style & SWT.EMBEDDED) == 0) {
196     if ((state & CANVAS) != 0 && (style & SWT.NO_FOCUS) == 0) {
197       imHandle = OS.gtk_im_multicontext_new ();
198       if (imHandle == 0) error (SWT.ERROR_NO_HANDLES);
199     }
200   }
201   if (scrolled) {
202     OS.gtk_container_add (parentHandle, fixedHandle);
203     OS.gtk_container_add (fixedHandle, scrolledHandle);
204     /*
205     * Force the scrolledWindow to have a single child that is
206     * not scrolled automatically.  Calling gtk_container_add
207     * seems to add the child correctly but cause a warning.
208     */
209     boolean warnings = display.getWarnings ();
210     display.setWarnings (false);
211     OS.gtk_container_add (scrolledHandle, handle);
212     display.setWarnings (warnings);
213     
214     OS.gtk_widget_show (fixedHandle);
215     OS.gtk_widget_show (scrolledHandle);
216     int hsp = (style & SWT.H_SCROLL) != 0 ? OS.GTK_POLICY_ALWAYS : OS.GTK_POLICY_NEVER;
217     int vsp = (style & SWT.V_SCROLL) != 0 ? OS.GTK_POLICY_ALWAYS : OS.GTK_POLICY_NEVER;
218     OS.gtk_scrolled_window_set_policy (scrolledHandle, hsp, vsp);
219     //TODO - CHECK WIDTH IS THERE ALREADY THEN DON'T SET
220     if (hasBorder ()) {
221       OS.gtk_scrolled_window_set_shadow_type (scrolledHandle, OS.GTK_SHADOW_ETCHED_IN);
222     }
223   } else {
224     OS.gtk_container_add (parentHandle, handle);    
225   }
226   OS.gtk_widget_show (handle);
227   if ((style & SWT.EMBEDDED) != 0) {
228     socketHandle = OS.gtk_socket_new ();
229     if (socketHandle == 0) SWT.error (SWT.ERROR_NO_HANDLES);
230     OS.gtk_container_add (handle, socketHandle);
231     OS.gtk_widget_show (socketHandle);
232     embeddedHandle = OS.gtk_socket_get_id (socketHandle);
233   }
234   if (imHandle != 0) {
235     long /*int*/ window = OS.GTK_WIDGET_WINDOW (handle);
236     if (window != 0) {
237       OS.gtk_im_context_set_client_window (imHandle, window);
238     }
239   }
240   if ((style & SWT.NO_REDRAW_RESIZE) != 0) {
241     OS.gtk_widget_set_redraw_on_allocate (handle, false);
242   }
243 }
244 
245 void deregister () {
246   super.deregister ();
247   if (socketHandle != 0) display.removeWidget (socketHandle);
248 }
249 
250 void enableWidget (boolean enabled) {
251   if ((state & CANVAS) != 0) return;
252   super.enableWidget (enabled);
253 }
254 
255 Menu [] findMenus (Control control) {
256   if (control == this) return new Menu [0];
257   Menu result [] = super.findMenus (control);
258   Control [] children = _getChildren ();
259   for (int i=0; i<children.length; i++) {
260     Control child = children [i];
261     Menu [] menuList = child.findMenus (control);
262     if (menuList.length != 0) {
263       Menu [] newResult = new Menu [result.length + menuList.length];
264       System.arraycopy (result, 0, newResult, 0, result.length);
265       System.arraycopy (menuList, 0, newResult, result.length, menuList.length);
266       result = newResult;
267     }
268   }
269   return result;
270 }
271 
272 void fixChildren (Shell newShell, Shell oldShell, Decorations newDecorations, Decorations oldDecorations, Menu [] menus) {
273   super.fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
274   Control [] children = _getChildren ();
275   for (int i=0; i<children.length; i++) {
276     children [i].fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
277   }
278 }
279 
280 void fixTabList (Control control) {
281   if (tabList == null) return;
282   int count = 0;
283   for (int i=0; i<tabList.length; i++) {
284     if (tabList [i] == control) count++;
285   }
286   if (count == 0) return;
287   Control [] newList = null;
288   int length = tabList.length - count;
289   if (length != 0) {
290     newList = new Control [length];
291     int index = 0;
292     for (int i=0; i<tabList.length; i++) {
293       if (tabList [i] != control) {
294         newList [index++] = tabList [i];
295       }
296     }
297   }
298   tabList = newList;
299 }
300 
301 long /*int*/ focusHandle () {
302   if (socketHandle != 0) return socketHandle;
303   return super.focusHandle ();
304 }
305 
306 boolean forceFocus (long /*int*/ focusHandle) {
307   if (socketHandle != 0) OS.GTK_WIDGET_SET_FLAGS (focusHandle, OS.GTK_CAN_FOCUS);
308   boolean result = super.forceFocus (focusHandle);
309   if (socketHandle != 0) OS.GTK_WIDGET_UNSET_FLAGS (focusHandle, OS.GTK_CAN_FOCUS);
310   return result;
311 }
312 
313 /**
314  * Returns an array containing the receiver's children.
315  * <p>
316  * Note: This is not the actual structure used by the receiver
317  * to maintain its list of children, so modifying the array will
318  * not affect the receiver. 
319  * </p>
320  *
321  * @return an array of children
322  *
323  * @exception SWTException <ul>
324  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
325  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
326  * </ul>
327  */
328 public Control [] getChildren () {
329   checkWidget();
330   return _getChildren ();
331 }
332 
333 int getChildrenCount () {
334   /*
335   * NOTE: The current implementation will count
336   * non-registered children.
337   */
338   long /*int*/ list = OS.gtk_container_get_children (handle);
339   if (list == 0) return 0;
340   int count = OS.g_list_length (list);
341   OS.g_list_free (list);
342   return count;
343 }
344 
345 /**
346  * Returns layout which is associated with the receiver, or
347  * null if one has not been set.
348  *
349  * @return the receiver's layout or null
350  *
351  * @exception SWTException <ul>
352  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
353  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
354  * </ul>
355  */
356 public Layout getLayout () {
357   checkWidget();
358   return layout;
359 }
360 
361 /**
362  * Gets the last specified tabbing order for the control.
363  *
364  * @return tabList the ordered list of controls representing the tab order
365  *
366  * @exception SWTException <ul>
367  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
368  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
369  * </ul>
370  * 
371  * @see #setTabList
372  */
373 public Control [] getTabList () {
374   checkWidget ();
375   Control [] tabList = _getTabList ();
376   if (tabList == null) {
377     int count = 0;
378     Control [] list =_getChildren ();
379     for (int i=0; i<list.length; i++) {
380       if (list [i].isTabGroup ()) count++;
381     }
382     tabList = new Control [count];
383     int index = 0;
384     for (int i=0; i<list.length; i++) {
385       if (list [i].isTabGroup ()) {
386         tabList [index++] = list [i];
387       }
388     }
389   }
390   return tabList;
391 }
392 
393 long /*int*/ gtk_button_press_event (long /*int*/ widget, long /*int*/ event) {
394   long /*int*/ result = super.gtk_button_press_event (widget, event);
395   if ((state & CANVAS) != 0) {
396     if ((style & SWT.NO_FOCUS) == 0 && hooksKeys ()) {
397       GdkEventButton gdkEvent = new GdkEventButton ();
398       OS.memmove (gdkEvent, event, GdkEventButton.sizeof);
399       if (gdkEvent.button == 1) {
400         if (getChildrenCount () == 0) setFocus ();
401       }
402     }
403   }
404   return result;
405 }
406 
407 long /*int*/ gtk_expose_event (long /*int*/ widget, long /*int*/ eventPtr) {
408   if ((state & OBSCURED) != 0) return 0;
409   if ((state & CANVAS) == 0) {
410     return super.gtk_expose_event (widget, eventPtr);
411   }
412   if ((style & SWT.NO_MERGE_PAINTS) == 0) {
413     return super.gtk_expose_event (widget, eventPtr);
414   }
415   if (!hooks (SWT.Paint) && !filters (SWT.Paint)) return 0;
416   GdkEventExpose gdkEvent = new GdkEventExpose ();
417   OS.memmove(gdkEvent, eventPtr, GdkEventExpose.sizeof);
418   long /*int*/ [] rectangles = new long /*int*/ [1];
419   int [] n_rectangles = new int [1];
420   OS.gdk_region_get_rectangles (gdkEvent.region, rectangles, n_rectangles);
421   GdkRectangle rect = new GdkRectangle ();
422   for (int i=0; i<n_rectangles[0]; i++) {
423     Event event = new Event ();
424     OS.memmove (rect, rectangles [0] + i * GdkRectangle.sizeof, GdkRectangle.sizeof);
425     event.x = rect.x;
426     event.y = rect.y;
427     event.width = rect.width;
428     event.height = rect.height;
429     GC gc = event.gc = new GC (this);
430     gc.setClipping (event.x, event.y, event.width, event.height);
431     sendEvent (SWT.Paint, event);
432     gc.dispose ();
433     event.gc = null;
434   }
435   OS.g_free (rectangles [0]);
436   return 0;
437 }
438 
439 long /*int*/ gtk_key_press_event (long /*int*/ widget, long /*int*/ event) {
440   long /*int*/ result = super.gtk_key_press_event (widget, event);
441   if (result != 0) return result;
442   /*
443   * Feature in GTK.  The default behavior when the return key
444   * is pressed is to select the default button.  This is not the
445   * expected behavior for Composite and its subclasses.  The
446   * fix is to avoid calling the default handler.
447   */
448   if ((state & CANVAS) != 0) {
449     GdkEventKey keyEvent = new GdkEventKey ();
450     OS.memmove (keyEvent, event, GdkEventKey.sizeof);
451     int key = keyEvent.keyval;
452     switch (key) {
453       case OS.GDK_Return:
454       case OS.GDK_KP_Enter: return 1;
455     }
456   }
457   return result;
458 }
459 
460 long /*int*/ gtk_focus (long /*int*/ widget, long /*int*/ directionType) {
461   if (widget == socketHandle) return 0;
462   return super.gtk_focus (widget, directionType);
463 }
464 
465 long /*int*/ gtk_focus_in_event (long /*int*/ widget, long /*int*/ event) {
466   long /*int*/ result = super.gtk_focus_in_event (widget, event);
467   return (state & CANVAS) != 0 ? 1 : result;
468 }
469 
470 long /*int*/ gtk_focus_out_event (long /*int*/ widget, long /*int*/ event) {
471   long /*int*/ result = super.gtk_focus_out_event (widget, event);
472   return (state & CANVAS) != 0 ? 1 : result;
473 }
474 
475 long /*int*/ gtk_realize (long /*int*/ widget) {
476   long /*int*/ result = super.gtk_realize (widget);
477   if ((style & SWT.NO_BACKGROUND) != 0) {
478     long /*int*/ window = OS.GTK_WIDGET_WINDOW (paintHandle ());
479     if (window != 0) OS.gdk_window_set_back_pixmap (window, 0, false);
480   }
481   return result;
482 }
483 
484 long /*int*/ gtk_scroll_child (long /*int*/ widget, long /*int*/ scrollType, long /*int*/ horizontal) {
485   /* Stop GTK scroll child signal for canvas */
486   OS.g_signal_stop_emission_by_name (widget, OS.scroll_child);
487   return 1;
488 }
489 
490 long /*int*/ gtk_style_set (long /*int*/ widget, long /*int*/ previousStyle) {
491   if ((style & SWT.NO_BACKGROUND) != 0) {
492     long /*int*/ window = OS.GTK_WIDGET_WINDOW (paintHandle ());
493     if (window != 0) OS.gdk_window_set_back_pixmap (window, 0, false);
494   }
495   return 0;
496 }
497 
498 boolean hasBorder () {
499   return (style & SWT.BORDER) != 0;
500 }
501 
502 void hookEvents () {
503   super.hookEvents ();
504   if ((state & CANVAS) != 0) {
505     OS.gtk_widget_add_events (handle, OS.GDK_POINTER_MOTION_HINT_MASK);
506     if (scrolledHandle != 0) {
507       OS.g_signal_connect (scrolledHandle, OS.scroll_child, display.windowProc4, SCROLL_CHILD);
508     }
509     if ((style & SWT.NO_BACKGROUND) != 0) {
510       OS.g_signal_connect (handle, OS.style_set, display.windowProc3, STYLE_SET);
511     }
512   }
513 }
514 
515 boolean hooksKeys () {
516   return hooks (SWT.KeyDown) || hooks (SWT.KeyUp);
517 }
518 
519 long /*int*/ imHandle () {
520   return imHandle;
521 }
522 
523 boolean isTabGroup() {
524   if ((state & CANVAS) != 0) return true;
525   return super.isTabGroup();
526 }
527 
528 /**
529  * If the receiver has a layout, asks the layout to <em>lay out</em>
530  * (that is, set the size and location of) the receiver's children. 
531  * If the receiver does not have a layout, do nothing.
532  * <p>
533  * This is equivalent to calling <code>layout(true)</code>.
534  * </p>
535  *
536  * @exception SWTException <ul>
537  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
538  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
539  * </ul>
540  */
541 public void layout () {
542   layout (true);
543 }
544 
545 /**
546  * If the receiver has a layout, asks the layout to <em>lay out</em>
547  * (that is, set the size and location of) the receiver's children. 
548  * If the the argument is <code>true</code> the layout must not rely
549  * on any cached information it is keeping about the children. If it
550  * is <code>false</code> the layout may (potentially) simplify the
551  * work it is doing by assuming that the state of the none of the
552  * receiver's children has changed since the last layout.
553  * If the receiver does not have a layout, do nothing.
554  *
555  * @param changed <code>true</code> if the layout must flush its caches, and <code>false</code> otherwise
556  *
557  * @exception SWTException <ul>
558  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
559  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
560  * </ul>
561  */
562 public void layout (boolean changed) {
563   checkWidget();
564   if (layout == null) return;
565   layout.layout (this, changed);
566 }
567 
568 void moveAbove (long /*int*/ child, long /*int*/ sibling) {
569   if (child == sibling) return;
570   long /*int*/ parentHandle = parentingHandle ();
571   GtkFixed fixed = new GtkFixed ();
572   OS.memmove (fixed, parentHandle);
573   long /*int*/ children = fixed.children;
574   if (children == 0) return;
575   long /*int*/ [] data = new long /*int*/ [1];
576   long /*int*/ [] widget = new long /*int*/ [1];
577   long /*int*/ childData = 0, childLink = 0, siblingLink = 0, temp = children;
578   while (temp != 0) {
579     OS.memmove (data, temp, OS.PTR_SIZEOF);
580     OS.memmove (widget, data [0], OS.PTR_SIZEOF);
581     if (child == widget [0]) {
582       childLink = temp;
583       childData = data [0];
584     } else if (sibling == widget [0]) {
585       siblingLink = temp;
586     }
587     if (childData != 0 && (sibling == 0 || siblingLink != 0)) break;
588     temp = OS.g_list_next (temp);
589   }
590   children = OS.g_list_remove_link (children, childLink);
591   if (siblingLink == 0 || OS.g_list_next (siblingLink) == 0) {
592     OS.g_list_free_1 (childLink);
593     children = OS.g_list_append (children, childData);
594   } else {
595     temp = OS.g_list_next (siblingLink);
596     OS.g_list_set_next (childLink, temp);
597     OS.g_list_set_previous (temp, childLink);
598     OS.g_list_set_previous (childLink, siblingLink);
599     OS.g_list_set_next (siblingLink, childLink);
600   }
601   fixed.children = children;
602   OS.memmove (parentHandle, fixed);
603 }
604 
605 void moveBelow (long /*int*/ child, long /*int*/ sibling) {
606   if (child == sibling) return;
607   long /*int*/ parentHandle = parentingHandle ();
608   if (sibling == 0 && parentHandle == fixedHandle) {
609     moveAbove (child, handle);
610     return;
611   }
612   GtkFixed fixed = new GtkFixed ();
613   OS.memmove (fixed, parentHandle);
614   long /*int*/ children = fixed.children;
615   if (children == 0) return;
616   long /*int*/ [] data = new long /*int*/ [1];
617   long /*int*/ [] widget = new long /*int*/ [1];
618   long /*int*/ childData = 0, childLink = 0, siblingLink = 0, temp = children;
619   while (temp != 0) {
620     OS.memmove (data, temp, OS.PTR_SIZEOF);
621     OS.memmove (widget, data [0], OS.PTR_SIZEOF);
622     if (child == widget [0]) {
623       childLink = temp;
624       childData = data [0];
625     } else if (sibling == widget [0]) {
626       siblingLink = temp;
627     }
628     if (childData != 0 && (sibling == 0 || siblingLink != 0)) break;
629     temp = OS.g_list_next (temp);
630   }
631   children = OS.g_list_remove_link (children, childLink);
632   if (siblingLink == 0 || OS.g_list_previous (siblingLink) == 0) {
633     OS.g_list_free_1 (childLink);
634     children = OS.g_list_prepend (children, childData);
635   } else {
636     temp = OS.g_list_previous (siblingLink);
637     OS.g_list_set_previous (childLink, temp);
638     OS.g_list_set_next (temp, childLink);
639     OS.g_list_set_next (childLink, siblingLink);
640     OS.g_list_set_previous (siblingLink, childLink);
641   }
642   fixed.children = children;
643   OS.memmove (parentHandle, fixed);
644 }
645 
646 Point minimumSize () {
647   Control [] children = _getChildren ();
648   int width = 0, height = 0;
649   for (int i=0; i<children.length; i++) {
650     Rectangle rect = children [i].getBounds ();
651     width = Math.max (width, rect.x + rect.width);
652     height = Math.max (height, rect.y + rect.height);
653   }
654   return new Point (width, height);
655 }
656 
657 long /*int*/ parentingHandle () {
658   if ((state & CANVAS) != 0) return handle;
659   return fixedHandle != 0 ? fixedHandle : handle;
660 }
661 
662 void register () {
663   super.register ();
664   if (socketHandle != 0) display.addWidget (socketHandle, this);
665 }
666 
667 void releaseChildren () {
668   Control [] children = _getChildren ();
669   for (int i=0; i<children.length; i++) {
670     Control child = children [i];
671     if (child != null && !child.isDisposed ()) child.releaseResources ();
672   }
673 }
674 
675 void releaseWidget () {
676   releaseChildren ();
677   super.releaseWidget ();
678   if (imHandle != 0) OS.g_object_unref (imHandle);
679   imHandle = 0;
680   layout = null;
681 }
682 
683 void removeControl (Control control) {
684   fixTabList (control);
685 }
686 
687 void resizeHandle (int width, int height) {
688   super.resizeHandle (width, height);
689   if (socketHandle != 0) OS.gtk_widget_set_size_request (socketHandle, width, height);
690 }
691 
692 boolean setBounds (int x, int y, int width, int height, boolean move, boolean resize) {
693   boolean changed = super.setBounds (x, y, width, height, move, resize);
694   if (changed && resize && layout != null) layout.layout (this, false);
695   return changed;
696 }
697 
698 public boolean setFocus () {
699   checkWidget();
700   Control [] children = _getChildren ();
701   for (int i=0; i<children.length; i++) {
702     Control child = children [i];
703     if (child.getVisible () && child.setFocus ()) return true;
704   }
705   return super.setFocus ();
706 }
707 
708 /**
709  * Sets the layout which is associated with the receiver to be
710  * the argument which may be null.
711  *
712  * @param layout the receiver's new layout or null
713  *
714  * @exception SWTException <ul>
715  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
716  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
717  * </ul>
718  */
719 public void setLayout (Layout layout) {
720   checkWidget();
721   this.layout = layout;
722 }
723 
724 boolean setTabGroupFocus (boolean next) {
725   if (isTabItem ()) return setTabItemFocus (next);
726   boolean takeFocus = (style & SWT.NO_FOCUS) == 0;
727   if ((state & CANVAS) != 0) takeFocus = hooksKeys ();
728   if (socketHandle != 0) takeFocus = true;
729   if (takeFocus  && setTabItemFocus (next)) return true;
730   Control [] children = _getChildren ();
731   for (int i=0; i<children.length; i++) {
732     Control child = children [i];
733     if (child.isTabItem () && child.setTabItemFocus (next)) return true;
734   }
735   return false;
736 }
737 
738 boolean setTabItemFocus (boolean next) {
739   if (!super.setTabItemFocus (next)) return false;
740   if (socketHandle != 0) {
741     int direction = next ? OS.GTK_DIR_TAB_FORWARD : OS.GTK_DIR_TAB_BACKWARD;
742     OS.GTK_WIDGET_UNSET_FLAGS (socketHandle, OS.GTK_HAS_FOCUS);
743     OS.gtk_widget_child_focus (socketHandle, direction);
744     OS.GTK_WIDGET_SET_FLAGS (socketHandle, OS.GTK_HAS_FOCUS);
745   }
746   return true;
747 }
748 
749 /**
750  * Sets the tabbing order for the specified controls to
751  * match the order that they occur in the argument list.
752  *
753  * @param tabList the ordered list of controls representing the tab order or null
754  *
755  * @exception IllegalArgumentException <ul>
756  *    <li>ERROR_INVALID_ARGUMENT - if a widget in the tabList is null or has been disposed</li> 
757  *    <li>ERROR_INVALID_PARENT - if widget in the tabList is not in the same widget tree</li>
758  * </ul>
759  * @exception SWTException <ul>
760  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
761  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
762  * </ul>
763  */
764 public void setTabList (Control [] tabList) {
765   checkWidget ();
766   if (tabList != null) {
767     for (int i=0; i<tabList.length; i++) {
768       Control control = tabList [i];
769       if (control == null) error (SWT.ERROR_INVALID_ARGUMENT);
770       if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
771       if (control.parent != this) error (SWT.ERROR_INVALID_PARENT);
772     }
773     Control [] newList = new Control [tabList.length];
774     System.arraycopy (tabList, 0, newList, 0, tabList.length);
775     tabList = newList;
776   } 
777   this.tabList = tabList;
778 }
779 
780 boolean translateMnemonic (Event event, Control control) {
781   if (super.translateMnemonic (event, control)) return true;
782   if (control != null) {
783     Control [] children = _getChildren ();
784     for (int i=0; i<children.length; i++) {
785       Control child = children [i];
786       if (child.translateMnemonic (event, control)) return true;
787     }
788   }
789   return false;
790 }
791 
792 int traversalCode(int key, GdkEventKey event) {
793   if ((state & CANVAS) != 0) {
794     if ((style & SWT.NO_FOCUS) != 0) return 0;
795     if (hooksKeys ()) return 0;
796   }
797   return super.traversalCode (key, event);
798 }
799 
800 boolean translateTraversal (GdkEventKey keyEvent) {
801   if (socketHandle != 0) return false;
802   return super.translateTraversal (keyEvent);
803 }
804 
805 }