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

Quick Search    Search Deep

Source code: org/eclipse/swt/widgets/Button.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.internal.*;
15  import org.eclipse.swt.internal.gtk.*;
16  import org.eclipse.swt.*;
17  import org.eclipse.swt.graphics.*;
18  import org.eclipse.swt.events.*;
19  
20  /**
21   * Instances of this class represent a selectable user interface object that
22   * issues notification when pressed and released. 
23   * <dl>
24   * <dt><b>Styles:</b></dt>
25   * <dd>ARROW, CHECK, PUSH, RADIO, TOGGLE, FLAT</dd>
26   * <dd>UP, DOWN, LEFT, RIGHT, CENTER</dd>
27   * <dt><b>Events:</b></dt>
28   * <dd>Selection</dd>
29   * </dl>
30   * <p>
31   * Note: Only one of the styles ARROW, CHECK, PUSH, RADIO, and TOGGLE 
32   * may be specified.
33   * </p><p>
34   * Note: Only one of the styles LEFT, RIGHT, and CENTER may be specified.
35   * </p><p>
36   * Note: Only one of the styles UP, DOWN, LEFT, and RIGHT may be specified
37   * when the ARROW style is specified.
38   * </p><p>
39   * IMPORTANT: This class is intended to be subclassed <em>only</em>
40   * within the SWT implementation.
41   * </p>
42   */
43  public class Button extends Control {
44    long /*int*/ boxHandle, labelHandle, imageHandle, arrowHandle, groupHandle;
45    boolean selected;
46    Image image;
47    String text;
48  
49  /**
50   * Constructs a new instance of this class given its parent
51   * and a style value describing its behavior and appearance.
52   * <p>
53   * The style value is either one of the style constants defined in
54   * class <code>SWT</code> which is applicable to instances of this
55   * class, or must be built by <em>bitwise OR</em>'ing together 
56   * (that is, using the <code>int</code> "|" operator) two or more
57   * of those <code>SWT</code> style constants. The class description
58   * lists the style constants that are applicable to the class.
59   * Style bits are also inherited from superclasses.
60   * </p>
61   *
62   * @param parent a composite control which will be the parent of the new instance (cannot be null)
63   * @param style the style of control to construct
64   *
65   * @exception IllegalArgumentException <ul>
66   *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
67   * </ul>
68   * @exception SWTException <ul>
69   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
70   *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
71   * </ul>
72   *
73   * @see SWT#ARROW
74   * @see SWT#CHECK
75   * @see SWT#PUSH
76   * @see SWT#RADIO
77   * @see SWT#TOGGLE
78   * @see SWT#FLAT
79   * @see SWT#LEFT
80   * @see SWT#RIGHT
81   * @see SWT#CENTER
82   * @see Widget#checkSubclass
83   * @see Widget#getStyle
84   */
85  public Button (Composite parent, int style) {
86    super (parent, checkStyle (style));
87  }
88  
89  static int checkStyle (int style) {
90    style = checkBits (style, SWT.PUSH, SWT.ARROW, SWT.CHECK, SWT.RADIO, SWT.TOGGLE, 0);
91    if ((style & (SWT.PUSH | SWT.TOGGLE)) != 0) {
92      return checkBits (style, SWT.CENTER, SWT.LEFT, SWT.RIGHT, 0, 0, 0);
93    }
94    if ((style & (SWT.CHECK | SWT.RADIO)) != 0) {
95      return checkBits (style, SWT.LEFT, SWT.RIGHT, SWT.CENTER, 0, 0, 0);
96    }
97    if ((style & SWT.ARROW) != 0) {
98      style |= SWT.NO_FOCUS;
99      return checkBits (style, SWT.UP, SWT.DOWN, SWT.LEFT, SWT.RIGHT, 0, 0);
100   }
101   return style;
102 }
103 
104 /**
105  * Adds the listener to the collection of listeners who will
106  * be notified when the control is selected, by sending
107  * it one of the messages defined in the <code>SelectionListener</code>
108  * interface.
109  * <p>
110  * <code>widgetSelected</code> is called when the control is selected.
111  * <code>widgetDefaultSelected</code> is not called.
112  * </p>
113  *
114  * @param listener the listener which should be notified
115  *
116  * @exception IllegalArgumentException <ul>
117  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
118  * </ul>
119  * @exception SWTException <ul>
120  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
121  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
122  * </ul>
123  *
124  * @see SelectionListener
125  * @see #removeSelectionListener
126  * @see SelectionEvent
127  */
128 public void addSelectionListener (SelectionListener listener) {
129   checkWidget ();
130   if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
131   TypedListener typedListener = new TypedListener (listener);
132   addListener (SWT.Selection,typedListener);
133   addListener (SWT.DefaultSelection,typedListener);
134 }
135 
136 public Point computeSize (int wHint, int hHint, boolean changed) {
137   checkWidget ();
138   if (wHint != SWT.DEFAULT && wHint < 0) wHint = 0;
139   if (hHint != SWT.DEFAULT && hHint < 0) hHint = 0;
140   int width = OS.GTK_WIDGET_WIDTH (fixedHandle);
141   int height = OS.GTK_WIDGET_HEIGHT (fixedHandle);
142   OS.gtk_widget_set_size_request (handle, wHint, hHint);
143   GtkRequisition requisition = new GtkRequisition ();
144   OS.gtk_widget_size_request (handle, requisition);
145   OS.gtk_widget_set_size_request (handle, width, height);
146   width = wHint == SWT.DEFAULT ? requisition.width : wHint;
147   height = hHint == SWT.DEFAULT ? requisition.height : hHint;
148   return new Point (width, height);  
149 }
150 
151 void createHandle (int index) {
152   state |= HANDLE;
153   int bits = SWT.ARROW | SWT.TOGGLE | SWT.CHECK | SWT.RADIO | SWT.PUSH;
154   fixedHandle = OS.gtk_fixed_new ();
155   if (fixedHandle == 0) error (SWT.ERROR_NO_HANDLES);
156   OS.gtk_fixed_set_has_window (fixedHandle, true);
157   switch (style & bits) {
158     case SWT.ARROW:
159       int arrow_type = OS.GTK_ARROW_UP;
160       if ((style & SWT.UP) != 0) arrow_type = OS.GTK_ARROW_UP;
161       if ((style & SWT.DOWN) != 0) arrow_type = OS.GTK_ARROW_DOWN;
162             if ((style & SWT.LEFT) != 0) arrow_type = OS.GTK_ARROW_LEFT;
163             if ((style & SWT.RIGHT) != 0) arrow_type = OS.GTK_ARROW_RIGHT;
164       handle = OS.gtk_button_new ();
165       if (handle == 0) error (SWT.ERROR_NO_HANDLES);
166       arrowHandle = OS.gtk_arrow_new (arrow_type, OS.GTK_SHADOW_OUT);
167       if (arrowHandle == 0) error (SWT.ERROR_NO_HANDLES);
168       break;
169     case SWT.TOGGLE:
170       handle = OS.gtk_toggle_button_new ();
171       if (handle == 0) error (SWT.ERROR_NO_HANDLES);
172       break;
173     case SWT.CHECK:
174       handle = OS.gtk_check_button_new ();
175       if (handle == 0) error (SWT.ERROR_NO_HANDLES);
176       break;
177     case SWT.RADIO:
178       groupHandle = OS.gtk_radio_button_new (0);
179       if (groupHandle == 0) error (SWT.ERROR_NO_HANDLES);
180       OS.g_object_ref (groupHandle);
181       OS.gtk_object_sink (groupHandle);
182       handle = OS.gtk_radio_button_new (OS.gtk_radio_button_get_group (groupHandle));
183       if (handle == 0) error (SWT.ERROR_NO_HANDLES);
184       break;
185     case SWT.PUSH:
186     default:
187       handle = OS.gtk_button_new ();
188       if (handle == 0) error (SWT.ERROR_NO_HANDLES);
189       OS.GTK_WIDGET_SET_FLAGS(handle, OS.GTK_CAN_DEFAULT);
190       break;
191   }
192   if ((style & SWT.ARROW) != 0) {
193     OS.gtk_container_add (handle, arrowHandle);
194     OS.gtk_widget_show (arrowHandle);
195   } else {
196     boxHandle = OS.gtk_hbox_new (false, 0);
197     if (boxHandle == 0) error (SWT.ERROR_NO_HANDLES);
198     labelHandle = OS.gtk_label_new_with_mnemonic (null);
199     if (labelHandle == 0) error (SWT.ERROR_NO_HANDLES);
200     imageHandle = OS.gtk_image_new ();
201     if (imageHandle == 0) error (SWT.ERROR_NO_HANDLES);
202     OS.gtk_container_add (handle, boxHandle);
203     OS.gtk_container_add (boxHandle, labelHandle);
204     OS.gtk_container_add (boxHandle, imageHandle);
205     OS.gtk_widget_show (boxHandle);
206     OS.gtk_widget_show (labelHandle);
207   }
208   long /*int*/ parentHandle = parent.parentingHandle ();
209   OS.gtk_container_add (parentHandle, fixedHandle);
210   OS.gtk_container_add (fixedHandle, handle);
211   OS.gtk_widget_show (fixedHandle);
212   OS.gtk_widget_show (handle);
213   
214   if ((style & SWT.ARROW) != 0) return;
215   if ((style & SWT.LEFT) != 0) {
216     OS.gtk_misc_set_alignment (labelHandle, 0.0f, 0.5f);
217     OS.gtk_label_set_justify (labelHandle, OS.GTK_JUSTIFY_LEFT);
218     OS.gtk_misc_set_alignment (imageHandle, 0.0f, 0.5f);
219     return;
220   }
221   if ((style & SWT.CENTER) != 0) {
222     OS.gtk_misc_set_alignment (labelHandle, 0.5f, 0.5f);
223     OS.gtk_label_set_justify (labelHandle, OS.GTK_JUSTIFY_CENTER);
224     OS.gtk_misc_set_alignment (imageHandle, 0.5f, 0.5f);
225     return;
226   }
227   if ((style & SWT.RIGHT) != 0) {
228     OS.gtk_misc_set_alignment (labelHandle, 1.0f, 0.5f);
229     OS.gtk_label_set_justify (labelHandle, OS.GTK_JUSTIFY_RIGHT);
230     OS.gtk_misc_set_alignment (imageHandle, 1.0f, 0.5f);
231     return;
232   }
233 }
234 
235 void createWidget (int index) {
236   super.createWidget (index);
237   text = "";
238 }
239 
240 void deregister () {
241   super.deregister ();
242   if (boxHandle != 0) display.removeWidget (boxHandle);
243   if (labelHandle != 0) display.removeWidget (labelHandle);
244   if (imageHandle != 0) display.removeWidget (imageHandle);
245   if (arrowHandle != 0) display.removeWidget (arrowHandle);
246 }
247 
248 long /*int*/ fontHandle () {
249   if (labelHandle != 0) return labelHandle;
250   return super.fontHandle ();
251 }
252 
253 /**
254  * Returns a value which describes the position of the
255  * text or image in the receiver. The value will be one of
256  * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>
257  * unless the receiver is an <code>ARROW</code> button, in 
258  * which case, the alignment will indicate the direction of
259  * the arrow (one of <code>LEFT</code>, <code>RIGHT</code>, 
260  * <code>UP</code> or <code>DOWN</code>).
261  *
262  * @return the alignment 
263  *
264  * @exception SWTException <ul>
265  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
266  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
267  * </ul>
268  */
269 public int getAlignment () {
270   checkWidget ();
271   if ((style & SWT.ARROW) != 0) {
272     if ((style & SWT.UP) != 0) return SWT.UP;
273     if ((style & SWT.DOWN) != 0) return SWT.DOWN;
274     if ((style & SWT.LEFT) != 0) return SWT.LEFT;
275     if ((style & SWT.RIGHT) != 0) return SWT.RIGHT;
276     return SWT.UP;
277   }
278   if ((style & SWT.LEFT) != 0) return SWT.LEFT;
279   if ((style & SWT.CENTER) != 0) return SWT.CENTER;
280   if ((style & SWT.RIGHT) != 0) return SWT.RIGHT;
281   return SWT.LEFT;
282 }
283 
284 /**
285  * Returns the receiver's image if it has one, or null
286  * if it does not.
287  *
288  * @return the receiver's image
289  *
290  * @exception SWTException <ul>
291  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
292  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
293  * </ul>
294  */
295 public Image getImage () {
296   checkWidget ();
297   return image;
298 }
299 
300 String getNameText () {
301   return getText ();
302 }
303 
304 /**
305  * Returns <code>true</code> if the receiver is selected,
306  * and false otherwise.
307  * <p>
308  * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
309  * it is selected when it is checked. When it is of type <code>TOGGLE</code>,
310  * it is selected when it is pushed in. If the receiver is of any other type,
311  * this method returns false.
312  *
313  * @return the selection state
314  *
315  * @exception SWTException <ul>
316  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
317  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
318  * </ul>
319  */
320 public boolean getSelection () {
321   checkWidget ();
322   if ((style & (SWT.CHECK | SWT.RADIO | SWT.TOGGLE)) == 0) return false;
323   return OS.gtk_toggle_button_get_active (handle);
324 }
325 
326 /**
327  * Returns the receiver's text, which will be an empty
328  * string if it has never been set or if the receiver is
329  * an <code>ARROW</code> button.
330  *
331  * @return the receiver's text
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 public String getText () {
339   checkWidget();
340   if ((style & SWT.ARROW) != 0) return "";
341   return text;
342 }
343 
344 long /*int*/ gtk_button_press_event (long /*int*/ widget, long /*int*/ event) {
345   long /*int*/ result = super.gtk_button_press_event (widget, event);
346   if (result != 0) return result;
347   if ((style & SWT.RADIO) != 0) selected  = getSelection ();
348   return result;
349 }
350 
351 long /*int*/ gtk_clicked (long /*int*/ widget) {
352   if ((style & SWT.RADIO) != 0) {
353     if ((parent.getStyle () & SWT.NO_RADIO_GROUP) != 0) {
354       setSelection (!selected);
355     } else {
356       selectRadio ();
357     }
358   }
359   postEvent (SWT.Selection);
360   return 0;
361 }
362 
363 long /*int*/ gtk_focus_in_event (long /*int*/ widget, long /*int*/ event) {
364   long /*int*/ result = super.gtk_focus_in_event (widget, event);
365   // widget could be disposed at this point
366   if (handle == 0) return 0;
367   if ((style & SWT.PUSH) != 0 && OS.GTK_WIDGET_HAS_DEFAULT (handle)) {
368     Decorations menuShell = menuShell ();
369     menuShell.defaultButton = this;
370   }
371   return result;
372 }
373 
374 long /*int*/ gtk_focus_out_event (long /*int*/ widget, long /*int*/ event) {
375   long /*int*/ result = super.gtk_focus_out_event (widget, event);
376   // widget could be disposed at this point
377   if (handle == 0) return 0;
378   if ((style & SWT.PUSH) != 0 && !OS.GTK_WIDGET_HAS_DEFAULT (handle)) {
379     Decorations menuShell = menuShell ();
380     if (menuShell.defaultButton == this) {
381       menuShell.defaultButton = null;
382     }
383   }
384   return result;
385 }
386 
387 long /*int*/ gtk_key_press_event (long /*int*/ widget, long /*int*/ event) {
388   long /*int*/ result = super.gtk_key_press_event (widget, event);
389   if (result != 0) return result;
390   if ((style & SWT.RADIO) != 0) selected  = getSelection ();
391   return result;
392 }
393 
394 void hookEvents () {
395   super.hookEvents();
396   OS.g_signal_connect (handle, OS.clicked, display.windowProc2, CLICKED);
397   if (labelHandle != 0) {
398     OS.g_signal_connect (labelHandle, OS.mnemonic_activate, display.windowProc3, MNEMONIC_ACTIVATE);
399   }
400 }
401 
402 boolean mnemonicHit (char key) {
403   if (labelHandle == 0) return false;
404   boolean result = super.mnemonicHit (labelHandle, key);
405   if (result) setFocus ();
406   return result;
407 }
408 
409 boolean mnemonicMatch (char key) {
410   if (labelHandle == 0) return false;
411   return mnemonicMatch (labelHandle, key);
412 }
413 
414 void register () {
415   super.register ();
416   if (boxHandle != 0) display.addWidget (boxHandle, this);
417   if (labelHandle != 0) display.addWidget (labelHandle, this);
418   if (imageHandle != 0) display.addWidget (imageHandle, this);
419   if (arrowHandle != 0) display.addWidget (arrowHandle, this);
420 }
421 
422 void releaseHandle () {
423   super.releaseHandle ();
424   boxHandle = imageHandle = labelHandle = arrowHandle = 0;
425 }
426 
427 void releaseWidget () {
428   super.releaseWidget ();
429   if (groupHandle != 0) OS.g_object_unref (groupHandle);
430   groupHandle = 0;
431   image = null;
432   text = null;
433 }
434 
435 /**
436  * Removes the listener from the collection of listeners who will
437  * be notified when the control is selected.
438  *
439  * @param listener the listener which should be notified
440  *
441  * @exception IllegalArgumentException <ul>
442  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
443  * </ul>
444  * @exception SWTException <ul>
445  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
446  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
447  * </ul>
448  *
449  * @see SelectionListener
450  * @see #addSelectionListener
451  */
452 public void removeSelectionListener (SelectionListener listener) {
453   checkWidget();
454   if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
455   if (eventTable == null) return;
456   eventTable.unhook (SWT.Selection, listener);
457   eventTable.unhook (SWT.DefaultSelection,listener);  
458 }
459 
460 void selectRadio () {
461   /*
462   * This code is intentionally commented.  When two groups
463   * of radio buttons with the same parent are separated by
464   * another control, the correct behavior should be that
465   * the two groups act independently.  This is consistent
466   * with radio tool and menu items.  The commented code
467   * implements this behavior.
468   */
469 //  int index = 0;
470 //  Control [] children = parent._getChildren ();
471 //  while (index < children.length && children [index] != this) index++;
472 //  int i = index - 1;
473 //  while (i >= 0 && children [i].setRadioSelection (false)) --i;
474 //  int j = index + 1;
475 //  while (j < children.length && children [j].setRadioSelection (false)) j++;
476 //  setSelection (true);
477   Control [] children = parent._getChildren ();
478   for (int i=0; i<children.length; i++) {
479     Control child = children [i];
480     if (this != child) child.setRadioSelection (false);
481   }
482   setSelection (true);
483 }
484 
485 /**
486  * Controls how text, images and arrows will be displayed
487  * in the receiver. The argument should be one of
488  * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>
489  * unless the receiver is an <code>ARROW</code> button, in 
490  * which case, the argument indicates the direction of
491  * the arrow (one of <code>LEFT</code>, <code>RIGHT</code>, 
492  * <code>UP</code> or <code>DOWN</code>).
493  *
494  * @param alignment the new alignment 
495  *
496  * @exception SWTException <ul>
497  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
498  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
499  * </ul>
500  */
501 public void setAlignment (int alignment) {
502   checkWidget ();
503   if ((style & SWT.ARROW) != 0) {
504     if ((style & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT)) == 0) return; 
505     style &= ~(SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT);
506     style |= alignment & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT);
507     int arrow_type = OS.GTK_ARROW_UP;
508     boolean isRTL = (style & SWT.RIGHT_TO_LEFT) != 0;
509     switch (alignment) {
510       case SWT.UP: arrow_type = OS.GTK_ARROW_UP; break;
511       case SWT.DOWN: arrow_type = OS.GTK_ARROW_DOWN; break;
512       case SWT.LEFT: arrow_type = isRTL? OS.GTK_ARROW_RIGHT : OS.GTK_ARROW_LEFT; break;
513       case SWT.RIGHT: arrow_type = isRTL? OS.GTK_ARROW_LEFT : OS.GTK_ARROW_RIGHT; break;
514     }
515     OS.gtk_arrow_set (arrowHandle, arrow_type, OS.GTK_SHADOW_OUT);
516     return;
517   }
518   if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) == 0) return;
519   style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
520   style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
521   if ((style & SWT.LEFT) != 0) {
522     OS.gtk_misc_set_alignment (labelHandle, 0.0f, 0.5f);
523     OS.gtk_label_set_justify (labelHandle, OS.GTK_JUSTIFY_LEFT);
524     OS.gtk_misc_set_alignment (imageHandle, 0.0f, 0.5f);
525     return;
526   }
527   if ((style & SWT.CENTER) != 0) {
528     OS.gtk_misc_set_alignment (labelHandle, 0.5f, 0.5f);
529     OS.gtk_label_set_justify (labelHandle, OS.GTK_JUSTIFY_CENTER);
530     OS.gtk_misc_set_alignment (imageHandle, 0.5f, 0.5f);
531     return;
532   }
533   if ((style & SWT.RIGHT) != 0) {
534     OS.gtk_misc_set_alignment (labelHandle, 1.0f, 0.5f);
535     OS.gtk_label_set_justify (labelHandle, OS.GTK_JUSTIFY_RIGHT);
536     OS.gtk_misc_set_alignment (imageHandle, 1.0f, 0.5f);
537     return;
538   }
539 }
540 
541 void setBackgroundColor (GdkColor color) {
542   super.setBackgroundColor (color);
543   setBackgroundColor(fixedHandle, color);
544   if (labelHandle != 0) setBackgroundColor(labelHandle, color);
545   if (imageHandle != 0) setBackgroundColor(imageHandle, color);
546 }
547 
548 boolean setBounds (int x, int y, int width, int height, boolean move, boolean resize) { 
549   boolean result = super.setBounds (x, y, width, height, move, resize);
550   /*
551   * Feature in GTK, GtkCheckButton and GtkRadioButton allocate
552   * only the minimum size necessary for its child. This causes the child
553   * alignment to fail. The fix is to set the child size to all available space
554   * excluding trimmings.
555   */
556   if (result && (style & (SWT.CHECK | SWT.RADIO)) != 0) {
557     int childHeight = 0, buttonWidth = 0, buttonHeight = 0;
558     GtkRequisition requisition = new GtkRequisition ();
559     OS.gtk_widget_size_request (handle, requisition);
560     buttonWidth = requisition.width;
561     buttonHeight = requisition.height;
562     OS.gtk_widget_size_request (boxHandle, requisition);
563     childHeight = requisition.height;
564     OS.gtk_widget_set_size_request (handle, -1, -1);
565     OS.gtk_widget_set_size_request (boxHandle, -1, -1);
566     OS.gtk_widget_size_request (handle, requisition);
567     int trim = requisition.width;
568     OS.gtk_widget_size_request (boxHandle, requisition);
569     trim -= requisition.width;
570     OS.gtk_widget_set_size_request (handle, buttonWidth, buttonHeight);
571     OS.gtk_widget_set_size_request (boxHandle, Math.max (1, width - trim), childHeight);
572   }
573   return result;
574 }
575   
576 void setFontDescription (long /*int*/ font) {
577   super.setFontDescription (font);
578   if (labelHandle != 0) OS.gtk_widget_modify_font (labelHandle, font);
579   if (imageHandle != 0) OS.gtk_widget_modify_font (imageHandle, font);
580 }
581 
582 boolean setRadioSelection (boolean value) {
583   if ((style & SWT.RADIO) == 0) return false;
584   if (getSelection () != value) {
585     setSelection (value);
586     postEvent (SWT.Selection);
587   }
588   return true;
589 }
590 
591 void setForegroundColor (GdkColor color) {
592   super.setForegroundColor (color);
593   OS.gtk_widget_modify_fg (fixedHandle, OS.GTK_STATE_NORMAL, color);
594   if (labelHandle != 0) OS.gtk_widget_modify_fg (labelHandle,  OS.GTK_STATE_NORMAL, color);
595   if (imageHandle != 0) OS.gtk_widget_modify_fg (imageHandle,  OS.GTK_STATE_NORMAL, color);
596 }
597 
598 /**
599  * Sets the receiver's image to the argument, which may be
600  * null indicating that no image should be displayed.
601  *
602  * @param image the image to display on the receiver (may be null)
603  *
604  * @exception IllegalArgumentException <ul>
605  *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
606  * </ul> 
607  * @exception SWTException <ul>
608  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
609  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
610  * </ul>
611  */
612 public void setImage (Image image) {
613   checkWidget ();
614   if ((style & SWT.ARROW) != 0) return;
615   if (image != null) {
616     if (image.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
617     OS.gtk_image_set_from_pixmap (imageHandle, image.pixmap, image.mask);
618     OS.gtk_widget_hide (labelHandle);
619     OS.gtk_widget_show (imageHandle);
620   } else {
621     OS.gtk_image_set_from_pixmap (imageHandle, 0, 0);
622     OS.gtk_widget_show (labelHandle);
623     OS.gtk_widget_hide (imageHandle);
624   }
625   this.image = image;
626   /*
627   * Bug in GTK.  For some reason, the button does not allocate the size of its internal
628   * children if its bounds is set before the image is set.  The fix is to force this by calling
629   * gtk_widget_size_request() (and throw the results away).
630   */
631   GtkRequisition requisition = new GtkRequisition ();
632   OS.gtk_widget_size_request (handle, requisition);
633 }
634 
635 void setOrientation () {
636   if ((style & SWT.RIGHT_TO_LEFT) != 0) {
637     OS.gtk_widget_set_direction (handle, OS.GTK_TEXT_DIR_RTL);
638     if (labelHandle != 0) OS.gtk_widget_set_direction (labelHandle, OS.GTK_TEXT_DIR_RTL);
639     if (imageHandle != 0) OS.gtk_widget_set_direction (imageHandle, OS.GTK_TEXT_DIR_RTL);
640     if (arrowHandle != 0) {
641       switch (style & (SWT.LEFT | SWT.RIGHT)) {
642         case SWT.LEFT: OS.gtk_arrow_set (arrowHandle, OS.GTK_ARROW_RIGHT, OS.GTK_SHADOW_OUT); break;
643         case SWT.RIGHT: OS.gtk_arrow_set (arrowHandle, OS.GTK_ARROW_LEFT, OS.GTK_SHADOW_OUT); break;
644       }
645     }
646   }
647 }
648 
649 /**
650  * Sets the selection state of the receiver, if it is of type <code>CHECK</code>, 
651  * <code>RADIO</code>, or <code>TOGGLE</code>.
652  *
653  * <p>
654  * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
655  * it is selected when it is checked. When it is of type <code>TOGGLE</code>,
656  * it is selected when it is pushed in.
657  *
658  * @param selected the new selection state
659  *
660  * @exception SWTException <ul>
661  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
662  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
663  * </ul>
664  */
665 public void setSelection (boolean selected) {
666   checkWidget();
667   if ((style & (SWT.CHECK | SWT.RADIO | SWT.TOGGLE)) == 0) return;
668   OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CLICKED);
669   OS.gtk_toggle_button_set_active (handle, selected);
670   if ((style & SWT.RADIO) != 0) OS.gtk_toggle_button_set_active (groupHandle, !selected);
671   OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CLICKED);
672 }
673 
674 /**
675  * Sets the receiver's text.
676  * <p>
677  * This method sets the button label.  The label may include
678  * the mnemonic character but must not contain line delimiters.
679  * </p>
680  * <p>
681  * Mnemonics are indicated by an '&amp' that causes the next
682  * character to be the mnemonic.  When the user presses a
683  * key sequence that matches the mnemonic, a selection
684  * event occurs. On most platforms, the mnemonic appears
685  * underlined but may be emphasised in a platform specific
686  * manner.  The mnemonic indicator character '&amp' can be
687  * escaped by doubling it in the string, causing a single
688  *'&amp' to be displayed.
689  * </p>
690  * 
691  * @param string the new text
692  *
693  * @exception IllegalArgumentException <ul>
694  *    <li>ERROR_NULL_ARGUMENT - if the text is null</li>
695  * </ul>
696  * @exception SWTException <ul>
697  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
698  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
699  * </ul>
700  */
701 public void setText (String string) {
702   checkWidget ();
703   if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
704   if ((style & SWT.ARROW) != 0) return;
705   text = string;
706   char [] chars = fixMnemonic (string);
707   byte [] buffer = Converter.wcsToMbcs (null, chars, true);
708   OS.gtk_label_set_text_with_mnemonic (labelHandle, buffer);
709   OS.gtk_widget_hide (imageHandle);
710   OS.gtk_widget_show (labelHandle);
711   /*
712   * Bug in GTK.  For some reason, the button does not allocate the size of its internal
713   * children if its bounds is set before the text is set.  The fix is to force this by calling
714   * gtk_widget_size_request() (and throw the results away).
715   */
716   GtkRequisition requisition = new GtkRequisition ();
717   OS.gtk_widget_size_request (handle, requisition);
718 }
719 
720 int traversalCode (int key, GdkEventKey event) {
721   int code = super.traversalCode (key, event);
722   if ((style & SWT.RADIO) != 0) code |= SWT.TRAVERSE_ARROW_NEXT | SWT.TRAVERSE_ARROW_PREVIOUS;
723   return code;
724 }
725 
726 }