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

Quick Search    Search Deep

Source code: org/eclipse/swt/widgets/ToolItem.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.*;
16  import org.eclipse.swt.internal.gtk.*;
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
22   * that represents a button in a tool bar.
23   * <dl>
24   * <dt><b>Styles:</b></dt>
25   * <dd>PUSH, CHECK, RADIO, SEPARATOR, DROP_DOWN</dd>
26   * <dt><b>Events:</b></dt>
27   * <dd>Selection</dd>
28   * </dl>
29   * <p>
30   * Note: Only one of the styles CHECK, PUSH, RADIO, SEPARATOR and DROP_DOWN 
31   * may be specified.
32   * </p><p>
33   * IMPORTANT: This class is <em>not</em> intended to be subclassed.
34   * </p>
35   */
36  public class ToolItem extends Item {
37    long /*int*/ boxHandle, arrowHandle, separatorHandle, labelHandle, imageHandle;
38    ToolBar parent;
39    Control control;
40    Image hotImage, disabledImage;
41    String toolTipText;
42    boolean drawHotImage;
43  
44  /**
45   * Constructs a new instance of this class given its parent
46   * (which must be a <code>ToolBar</code>) and a style value
47   * describing its behavior and appearance. The item is added
48   * to the end of the items maintained by its parent.
49   * <p>
50   * The style value is either one of the style constants defined in
51   * class <code>SWT</code> which is applicable to instances of this
52   * class, or must be built by <em>bitwise OR</em>'ing together 
53   * (that is, using the <code>int</code> "|" operator) two or more
54   * of those <code>SWT</code> style constants. The class description
55   * lists the style constants that are applicable to the class.
56   * Style bits are also inherited from superclasses.
57   * </p>
58   *
59   * @param parent a composite control which will be the parent of the new instance (cannot be null)
60   * @param style the style of control to construct
61   *
62   * @exception IllegalArgumentException <ul>
63   *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
64   * </ul>
65   * @exception SWTException <ul>
66   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
67   *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
68   * </ul>
69   *
70   * @see SWT#PUSH
71   * @see SWT#CHECK
72   * @see SWT#RADIO
73   * @see SWT#SEPARATOR
74   * @see SWT#DROP_DOWN
75   * @see Widget#checkSubclass
76   * @see Widget#getStyle
77   */
78  public ToolItem (ToolBar parent, int style) {
79    super (parent, checkStyle (style));
80    this.parent = parent;
81    createWidget (parent.getItemCount ());
82  }
83  
84  /**
85   * Constructs a new instance of this class given its parent
86   * (which must be a <code>ToolBar</code>), a style value
87   * describing its behavior and appearance, and the index
88   * at which to place it in the items maintained by its parent.
89   * <p>
90   * The style value is either one of the style constants defined in
91   * class <code>SWT</code> which is applicable to instances of this
92   * class, or must be built by <em>bitwise OR</em>'ing together 
93   * (that is, using the <code>int</code> "|" operator) two or more
94   * of those <code>SWT</code> style constants. The class description
95   * lists the style constants that are applicable to the class.
96   * Style bits are also inherited from superclasses.
97   * </p>
98   *
99   * @param parent a composite control which will be the parent of the new instance (cannot be null)
100  * @param style the style of control to construct
101  * @param index the index to store the receiver in its parent
102  *
103  * @exception IllegalArgumentException <ul>
104  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
105  * </ul>
106  * @exception SWTException <ul>
107  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
108  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
109  * </ul>
110  *
111  * @see SWT#PUSH
112  * @see SWT#CHECK
113  * @see SWT#RADIO
114  * @see SWT#SEPARATOR
115  * @see SWT#DROP_DOWN
116  * @see Widget#checkSubclass
117  * @see Widget#getStyle
118  */
119 public ToolItem (ToolBar parent, int style, int index) {
120   super (parent, checkStyle (style));
121   this.parent = parent;
122   int count = parent.getItemCount ();
123   if (!(0 <= index && index <= count)) {
124     error (SWT.ERROR_ITEM_NOT_ADDED);
125   }
126   createWidget (index);
127 }
128 
129 /**
130  * Adds the listener to the collection of listeners who will
131  * be notified when the control is selected, by sending
132  * it one of the messages defined in the <code>SelectionListener</code>
133  * interface.
134  * <p>
135  * When <code>widgetSelected</code> is called when the mouse is over the arrow portion of a drop-down tool,
136  * the event object detail field contains the value <code>SWT.ARROW</code>.
137  * <code>widgetDefaultSelected</code> is not called.
138  * </p>
139  *
140  * @param listener the listener which should be notified
141  *
142  * @exception IllegalArgumentException <ul>
143  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
144  * </ul>
145  * @exception SWTException <ul>
146  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
147  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
148  * </ul>
149  *
150  * @see SelectionListener
151  * @see #removeSelectionListener
152  * @see SelectionEvent
153  */
154 public void addSelectionListener(SelectionListener listener) {
155   checkWidget();
156   if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
157   TypedListener typedListener = new TypedListener (listener);
158   addListener (SWT.Selection,typedListener);
159   addListener (SWT.DefaultSelection,typedListener);
160 }
161 
162 void createHandle (int index) {
163   state |= HANDLE;
164   if ((style & SWT.SEPARATOR) == 0) {
165     boxHandle = (parent.style & SWT.RIGHT) != 0 ? OS.gtk_hbox_new (false, 0) : OS.gtk_vbox_new (false, 0);
166     if (boxHandle == 0) error (SWT.ERROR_NO_HANDLES);
167     labelHandle = OS.gtk_label_new_with_mnemonic (null);
168     if (labelHandle == 0) error (SWT.ERROR_NO_HANDLES);
169     imageHandle = OS.gtk_image_new ();
170     if (imageHandle == 0) error (SWT.ERROR_NO_HANDLES);
171     OS.gtk_container_add (boxHandle, imageHandle);
172     OS.gtk_container_add (boxHandle, labelHandle);
173     OS.gtk_widget_show (boxHandle);
174   }  
175   int bits = SWT.SEPARATOR | SWT.RADIO | SWT.CHECK | SWT.PUSH | SWT.DROP_DOWN;
176   switch (style & bits) {
177     case SWT.SEPARATOR:
178       handle = OS.gtk_hbox_new (false, 0);
179       if (handle == 0) error (SWT.ERROR_NO_HANDLES);
180       boolean isVertical = (parent.style & SWT.VERTICAL) != 0;
181       separatorHandle = isVertical ? OS.gtk_hseparator_new() : OS.gtk_vseparator_new();
182       if (separatorHandle == 0) error (SWT.ERROR_NO_HANDLES);
183       OS.gtk_widget_set_size_request (separatorHandle, isVertical ? 15 : 6, isVertical ? 6 : 15);
184       OS.gtk_widget_set_size_request (handle, isVertical ? 15 : 6, isVertical ? 6 : 15);
185       OS.gtk_container_add (handle, separatorHandle);
186       OS.gtk_widget_show (separatorHandle);
187       break;
188     case SWT.DROP_DOWN:
189       handle = OS.gtk_button_new ();
190       if (handle == 0) error (SWT.ERROR_NO_HANDLES);
191       long /*int*/ arrowBoxHandle = OS.gtk_hbox_new (false, 0);
192       if (arrowBoxHandle == 0) error(SWT.ERROR_NO_HANDLES);
193       arrowHandle = OS.gtk_arrow_new (OS.GTK_ARROW_DOWN, OS.GTK_SHADOW_NONE);
194       if (arrowHandle == 0) error (SWT.ERROR_NO_HANDLES);
195       OS.gtk_widget_set_size_request (arrowHandle, 8, 6);
196       OS.gtk_container_add (handle, arrowBoxHandle);
197       OS.gtk_container_add (arrowBoxHandle, boxHandle);  
198       OS.gtk_container_add (arrowBoxHandle, arrowHandle);  
199       OS.gtk_widget_show (arrowBoxHandle);
200       OS.gtk_widget_show (arrowHandle);
201       break;
202     case SWT.RADIO:
203       /*
204       * This code is intentionally commented.  Because GTK
205       * enforces radio behavior in a button group a radio group
206       * is not created for each set of contiguous buttons, each
207       * radio button will not draw unpressed.  The fix is to use
208       * toggle buttons instead.
209       */
210 //      handle = OS.gtk_radio_button_new (0);
211 //      if (handle == 0) error (SWT.ERROR_NO_HANDLES);
212 //      OS.gtk_toggle_button_set_mode (handle, false);
213 //      OS.gtk_container_add (handle, boxHandle);  
214 //      break;
215     case SWT.CHECK:
216       handle = OS.gtk_toggle_button_new ();
217       if (handle == 0) error (SWT.ERROR_NO_HANDLES);
218       OS.gtk_toggle_button_set_mode (handle, false);
219       OS.gtk_container_add (handle, boxHandle);  
220       break;
221     case SWT.PUSH:
222     default:
223       handle = OS.gtk_button_new ();
224       if (handle == 0) error (SWT.ERROR_NO_HANDLES);
225       OS.gtk_container_add (handle, boxHandle);
226       break;
227   }
228   if ((style & SWT.SEPARATOR) == 0) {
229     int [] relief = new int [1];
230     OS.gtk_widget_style_get (parent.handle, OS.button_relief, relief, 0);
231     OS.gtk_button_set_relief (handle, relief [0]);
232   }
233   OS.GTK_WIDGET_UNSET_FLAGS (handle, OS.GTK_CAN_FOCUS);
234   OS.gtk_widget_show (handle);
235   OS.gtk_toolbar_insert_widget (parent.handle, handle, null, null, index);
236   setForegroundColor (parent.getForegroundColor ());
237   setFontDescription (parent.getFontDescription ());
238 }
239 
240 void deregister() {
241   super.deregister ();
242   if (labelHandle != 0) display.removeWidget (labelHandle);
243 }
244 
245 /**
246  * Returns a rectangle describing the receiver's size and location
247  * relative to its parent.
248  *
249  * @return the receiver's bounding rectangle
250  *
251  * @exception SWTException <ul>
252  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
253  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
254  * </ul>
255  */
256 public Rectangle getBounds () {
257   checkWidget();
258   long /*int*/ topHandle = topHandle ();
259   int x = OS.GTK_WIDGET_X (topHandle);
260   int y = OS.GTK_WIDGET_Y (topHandle);
261   int width = OS.GTK_WIDGET_WIDTH (topHandle);
262   int height = OS.GTK_WIDGET_HEIGHT (topHandle);
263   return new Rectangle (x, y, width, height);
264 }
265 
266 /**
267  * Returns the control that is used to fill the bounds of
268  * the item when the items is a <code>SEPARATOR</code>.
269  *
270  * @return the control
271  *
272  * @exception SWTException <ul>
273  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
274  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
275  * </ul>
276  */
277 public Control getControl () {
278   checkWidget();
279   return control;
280 }
281 
282 /**
283  * Returns the receiver's disabled image if it has one, or null
284  * if it does not.
285  * <p>
286  * The disabled image is displayed when the receiver is disabled.
287  * </p>
288  *
289  * @return the receiver's disabled image
290  *
291  * @exception SWTException <ul>
292  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
293  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
294  * </ul>
295  */
296 public Image getDisabledImage () {
297   checkWidget();
298   return disabledImage;
299 }
300 
301 /**
302  * Returns <code>true</code> if the receiver is enabled, and
303  * <code>false</code> otherwise. A disabled control is typically
304  * not selectable from the user interface and draws with an
305  * inactive or "grayed" look.
306  *
307  * @return the receiver's enabled state
308  *
309  * @exception SWTException <ul>
310  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
311  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
312  * </ul>
313  * 
314  * @see #isEnabled
315  */
316 public boolean getEnabled () {
317   checkWidget();
318   long /*int*/ topHandle = topHandle ();
319   return OS.GTK_WIDGET_SENSITIVE (topHandle);
320 }
321 
322 /**
323  * Returns the receiver's hot image if it has one, or null
324  * if it does not.
325  * <p>
326  * The hot image is displayed when the mouse enters the receiver.
327  * </p>
328  *
329  * @return the receiver's hot image
330  *
331  * @exception SWTException <ul>
332  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
333  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
334  * </ul>
335  */
336 public Image getHotImage () {
337   checkWidget();
338   return hotImage;
339 }
340 
341 /**
342  * Returns the receiver's parent, which must be a <code>ToolBar</code>.
343  *
344  * @return the receiver's parent
345  *
346  * @exception SWTException <ul>
347  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
348  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
349  * </ul>
350  */
351 public ToolBar getParent () {
352   checkWidget();
353   if (parent == null) error (SWT.ERROR_WIDGET_DISPOSED);
354   return parent;
355 }
356 
357 /**
358  * Returns <code>true</code> if the receiver is selected,
359  * and false otherwise.
360  * <p>
361  * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
362  * it is selected when it is checked (which some platforms draw as a
363  * pushed in button). If the receiver is of any other type, this method
364  * returns false.
365  * </p>
366  *
367  * @return the selection state
368  *
369  * @exception SWTException <ul>
370  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
371  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
372  * </ul>
373  */
374 public boolean getSelection () {
375   checkWidget();
376   if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return false;
377   return OS.gtk_toggle_button_get_active (handle);
378 }
379 
380 /**
381  * Returns the receiver's tool tip text, or null if it has not been set.
382  *
383  * @return the receiver's tool tip text
384  *
385  * @exception SWTException <ul>
386  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
387  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
388  * </ul>
389  */
390 public String getToolTipText () {
391   checkWidget();
392   return toolTipText;
393 }
394 
395 /**
396  * Gets the width of the receiver.
397  *
398  * @return the width
399  *
400  * @exception SWTException <ul>
401  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
402  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
403  * </ul>
404  */
405 public int getWidth () {
406   checkWidget();
407   long /*int*/ topHandle = topHandle ();
408   return OS.GTK_WIDGET_WIDTH (topHandle);
409 }
410 
411 long /*int*/ gtk_button_press_event (long /*int*/ widget, long /*int*/ event) {
412   GdkEventButton gdkEvent = new GdkEventButton();
413   OS.memmove(gdkEvent, event, GdkEventButton.sizeof);
414   double x = gdkEvent.x;
415   gdkEvent.x += OS.GTK_WIDGET_X(handle);
416   double y = gdkEvent.y;
417   gdkEvent.y += OS.GTK_WIDGET_Y(handle);
418   OS.memmove(event, gdkEvent, GdkEventButton.sizeof);
419   parent.gtk_button_press_event (widget, event);
420   gdkEvent.x = x;
421   gdkEvent.y = y;
422   OS.memmove(event, gdkEvent, GdkEventButton.sizeof);
423   return 0;
424 }
425 
426 long /*int*/ gtk_button_release_event (long /*int*/ widget, long /*int*/ event) {
427   GdkEventButton gdkEvent = new GdkEventButton();
428   OS.memmove(gdkEvent, event, GdkEventButton.sizeof);
429   double x = gdkEvent.x;
430   gdkEvent.x += OS.GTK_WIDGET_X(handle);
431   double y = gdkEvent.y;
432   gdkEvent.y += OS.GTK_WIDGET_Y(handle);
433   OS.memmove(event, gdkEvent, GdkEventButton.sizeof);
434   parent.gtk_button_release_event (widget, event);
435   gdkEvent.x = x;
436   gdkEvent.y = y;
437   OS.memmove(event, gdkEvent, GdkEventButton.sizeof);
438   return 0;
439 }
440 
441 long /*int*/ gtk_clicked (long /*int*/ widget) {
442   Event event = new Event ();
443   if ((style & SWT.DROP_DOWN) != 0) {
444     long /*int*/ eventPtr = OS.gtk_get_current_event ();
445     if (eventPtr != 0) {
446       GdkEvent gdkEvent = new GdkEvent ();
447       OS.memmove (gdkEvent, eventPtr, GdkEvent.sizeof);
448       switch (gdkEvent.type) {
449         case OS.GDK_BUTTON_PRESS:
450         case OS.GDK_2BUTTON_PRESS: 
451         case OS.GDK_BUTTON_RELEASE: {
452           double [] x_win = new double [1];
453           double [] y_win = new double [1];
454           OS.gdk_event_get_coords (eventPtr, x_win, y_win);
455           if ((int) x_win [0] > OS.GTK_WIDGET_WIDTH (boxHandle)) {
456             event.detail = SWT.ARROW;
457             long /*int*/ topHandle = topHandle ();
458             event.x = OS.GTK_WIDGET_X (topHandle);
459             event.y = OS.GTK_WIDGET_Y (topHandle) + OS.GTK_WIDGET_HEIGHT (topHandle);
460           }
461           break;
462         }
463       }
464       OS.gdk_event_free (eventPtr);
465     }
466   }
467   if ((style & SWT.RADIO) != 0) {
468     if ((parent.getStyle () & SWT.NO_RADIO_GROUP) == 0) {
469       selectRadio ();
470     }
471   }
472   postEvent (SWT.Selection, event);
473   return 0;
474 }
475 
476 long /*int*/ gtk_enter_notify_event (long /*int*/ widget, long /*int*/ event) {
477   drawHotImage = (parent.style & SWT.FLAT) != 0 && hotImage != null;
478   if (drawHotImage && imageHandle != 0) {
479     OS.gtk_image_set_from_pixmap (imageHandle, hotImage.pixmap, hotImage.mask);
480   }
481   return 0;
482 }
483 
484 long /*int*/ gtk_event_after (long /*int*/ widget, long /*int*/ gdkEvent) {
485   GdkEvent event = new GdkEvent ();
486   OS.memmove (event, gdkEvent, GdkEvent.sizeof);
487   switch (event.type) {
488     case OS.GDK_BUTTON_PRESS: {
489       GdkEventButton gdkEventButton = new GdkEventButton ();
490       OS.memmove (gdkEventButton, gdkEvent, GdkEventButton.sizeof);
491       if (gdkEventButton.button == 3) {
492         parent.showMenu ((int) gdkEventButton.x_root, (int) gdkEventButton.y_root);
493       }
494       break;
495     }
496   }  
497   return 0;
498 }
499 
500 long /*int*/ gtk_focus_out_event (long /*int*/ widget, long /*int*/ event) {
501   OS.GTK_WIDGET_UNSET_FLAGS (handle, OS.GTK_CAN_FOCUS);
502   parent.lastFocus = this;
503   return 0;
504 }
505 
506 long /*int*/ gtk_leave_notify_event (long /*int*/ widget, long /*int*/ event) {
507   if (drawHotImage) {
508     drawHotImage = false;
509     if (imageHandle != 0 && image != null) {
510       OS.gtk_image_set_from_pixmap (imageHandle, image.pixmap, image.mask);
511     }  
512   }
513   return 0;
514 }
515 
516 long /*int*/ gtk_mnemonic_activate (long /*int*/ widget, long /*int*/ arg1) {
517   return parent.gtk_mnemonic_activate (widget, arg1);
518 }
519 
520 boolean hasFocus () {
521   return OS.GTK_WIDGET_HAS_FOCUS (handle);
522 }
523 
524 void hookEvents () {
525   super.hookEvents ();
526   if ((style & SWT.SEPARATOR) != 0) return;
527   long /*int*/ windowProc2 = display.windowProc2;
528   long /*int*/ windowProc3 = display.windowProc3;
529   OS.g_signal_connect (handle, OS.clicked, windowProc2, CLICKED);
530   OS.g_signal_connect (handle, OS.enter_notify_event, windowProc3, ENTER_NOTIFY_EVENT);
531   OS.g_signal_connect (handle, OS.leave_notify_event, windowProc3, LEAVE_NOTIFY_EVENT);
532   if (labelHandle != 0) OS.g_signal_connect (labelHandle, OS.mnemonic_activate, display.windowProc3, MNEMONIC_ACTIVATE);
533 
534   OS.g_signal_connect (handle, OS.focus_out_event, windowProc3, FOCUS_OUT_EVENT);
535 
536   /*
537   * Feature in GTK.  Usually, GTK widgets propagate all events to their
538   * parent when they are done their own processing.  However, in contrast
539   * to other widgets, the buttons that make up the tool items, do not propagate
540   * the mouse up/down events. It is interesting to note that they DO propagate
541   * mouse motion events.  The fix is to explicitly forward mouse up/down events
542   * to the parent.
543   */
544   int mask =
545     OS.GDK_EXPOSURE_MASK | OS.GDK_POINTER_MOTION_MASK |
546     OS.GDK_BUTTON_PRESS_MASK | OS.GDK_BUTTON_RELEASE_MASK | 
547     OS.GDK_ENTER_NOTIFY_MASK | OS.GDK_LEAVE_NOTIFY_MASK | 
548     OS.GDK_KEY_PRESS_MASK | OS.GDK_KEY_RELEASE_MASK |
549     OS.GDK_FOCUS_CHANGE_MASK;
550   OS.gtk_widget_add_events (handle, mask);
551   OS.g_signal_connect (handle, OS.button_press_event, windowProc3, BUTTON_PRESS_EVENT);
552   OS.g_signal_connect (handle, OS.button_release_event, windowProc3, BUTTON_RELEASE_EVENT);
553   OS.g_signal_connect (handle, OS.event_after, windowProc3, EVENT_AFTER);
554 }
555 
556 /**
557  * Returns <code>true</code> if the receiver is enabled and all
558  * of the receiver's ancestors are enabled, and <code>false</code>
559  * otherwise. A disabled control is typically not selectable from the
560  * user interface and draws with an inactive or "grayed" look.
561  *
562  * @return the receiver's enabled state
563  *
564  * @exception SWTException <ul>
565  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
566  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
567  * </ul>
568  * 
569  * @see #getEnabled
570  */
571 public boolean isEnabled () {
572   checkWidget();
573   return getEnabled () && parent.isEnabled ();
574 }
575 
576 void register () {
577   super.register ();
578   if (labelHandle != 0) display.addWidget (labelHandle, this);
579 }
580 
581 void releaseHandle () {
582   super.releaseHandle ();
583   boxHandle = arrowHandle = separatorHandle = labelHandle = imageHandle = 0;
584 }
585 
586 void releaseWidget () {
587   /* Reparent the control back to the toolbar */
588   if (control != null) setControl (null);
589   super.releaseWidget ();
590   if (parent.lastFocus == this) parent.lastFocus = null;
591   parent = null;
592   control = null;
593   hotImage = disabledImage = null;
594   toolTipText = null;
595 }
596 
597 /**
598  * Removes the listener from the collection of listeners who will
599  * be notified when the control is selected.
600  *
601  * @param listener the listener which should be notified
602  *
603  * @exception IllegalArgumentException <ul>
604  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
605  * </ul>
606  * @exception SWTException <ul>
607  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
608  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
609  * </ul>
610  *
611  * @see SelectionListener
612  * @see #addSelectionListener
613  */
614 public void removeSelectionListener(SelectionListener listener) {
615   checkWidget();
616   if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
617   if (eventTable == null) return;
618   eventTable.unhook (SWT.Selection, listener);
619   eventTable.unhook (SWT.DefaultSelection,listener);  
620 }
621 
622 void selectRadio () {
623   int index = 0;
624   ToolItem [] items = parent.getItems ();
625   while (index < items.length && items [index] != this) index++;
626   int i = index - 1;
627   while (i >= 0 && items [i].setRadioSelection (false)) --i;
628   int j = index + 1;
629   while (j < items.length && items [j].setRadioSelection (false)) j++;
630   setSelection (true);
631 }
632 
633 /**
634  * Sets the control that is used to fill the bounds of
635  * the item when the items is a <code>SEPARATOR</code>.
636  *
637  * @param control the new control
638  *
639  * @exception IllegalArgumentException <ul>
640  *    <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li> 
641  *    <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</li>
642  * </ul>
643  * @exception SWTException <ul>
644  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
645  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
646  * </ul>
647  */
648 public void setControl (Control control) {
649   checkWidget ();
650   if (control != null) {
651     if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
652     if (control.parent != parent) error (SWT.ERROR_INVALID_PARENT);
653   }
654   if ((style & SWT.SEPARATOR) == 0) return;
655   Control newControl = control;
656   Control oldControl = this.control;
657   if (oldControl == newControl) return;
658   this.control = newControl;
659   long /*int*/ parentHandle = parent.parentingHandle ();
660   if (oldControl != null) {
661     OS.gtk_widget_reparent (oldControl.topHandle(), parentHandle);
662   }
663   if (newControl != null) {
664     OS.gtk_widget_reparent (newControl.topHandle(), parentHandle);
665     newControl.setBounds (getBounds ());
666     OS.gtk_widget_reparent (newControl.topHandle(), handle);
667     OS.gtk_widget_hide (separatorHandle);
668   } else {
669     OS.gtk_widget_show (separatorHandle);
670   }
671 }
672 
673 /**
674  * Sets the receiver's disabled image to the argument, which may be
675  * null indicating that no disabled image should be displayed.
676  * <p>
677  * The disbled image is displayed when the receiver is disabled.
678  * </p>
679  *
680  * @param image the disabled image to display on the receiver (may be null)
681  *
682  * @exception IllegalArgumentException <ul>
683  *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li> 
684  * </ul>
685  * @exception SWTException <ul>
686  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
687  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
688  * </ul>
689  */
690 public void setDisabledImage (Image image) {
691   checkWidget();
692   if ((style & SWT.SEPARATOR) != 0) return;
693   disabledImage = image;
694 }
695 
696 /**
697  * Enables the receiver if the argument is <code>true</code>,
698  * and disables it otherwise.
699  * <p>
700  * A disabled control is typically
701  * not selectable from the user interface and draws with an
702  * inactive or "grayed" look.
703  * </p>
704  *
705  * @param enabled the new enabled state
706  *
707  * @exception SWTException <ul>
708  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
709  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
710  * </ul>
711  */
712 public void setEnabled (boolean enabled) {
713   checkWidget();
714   long /*int*/ topHandle = topHandle ();
715   OS.gtk_widget_set_sensitive (topHandle, enabled);
716 }
717 
718 boolean setFocus () {
719   if ((style & SWT.SEPARATOR) != 0) return false;
720   OS.GTK_WIDGET_SET_FLAGS (handle, OS.GTK_CAN_FOCUS);
721   OS.gtk_widget_grab_focus (handle);
722   boolean result = OS.gtk_widget_is_focus (handle);
723   if (!result) OS.GTK_WIDGET_UNSET_FLAGS (handle, OS.GTK_CAN_FOCUS);
724   return result;
725 }
726 
727 void setFontDescription (long /*int*/ font) {
728   OS.gtk_widget_modify_font (handle, font);
729   if (labelHandle != 0) OS.gtk_widget_modify_font (labelHandle, font);
730   if (imageHandle != 0) OS.gtk_widget_modify_font (imageHandle, font);
731 }
732 
733 void setForegroundColor (GdkColor color) {
734   OS.gtk_widget_modify_fg (handle,  OS.GTK_STATE_NORMAL, color);
735   if (labelHandle != 0) OS.gtk_widget_modify_fg (labelHandle,  OS.GTK_STATE_NORMAL, color);
736   if (imageHandle != 0) OS.gtk_widget_modify_fg (imageHandle,  OS.GTK_STATE_NORMAL, color);
737 }
738 
739 /**
740  * Sets the receiver's hot image to the argument, which may be
741  * null indicating that no hot image should be displayed.
742  * <p>
743  * The hot image is displayed when the mouse enters the receiver.
744  * </p>
745  *
746  * @param image the hot image to display on the receiver (may be null)
747  *
748  * @exception IllegalArgumentException <ul>
749  *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li> 
750  * </ul>
751  * @exception SWTException <ul>
752  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
753  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
754  * </ul>
755  */
756 public void setHotImage (Image image) {
757   checkWidget();
758   if ((style & SWT.SEPARATOR) != 0) return;
759   hotImage = image;
760 }
761 
762 public void setImage (Image image) {
763   checkWidget();
764   if ((style & SWT.SEPARATOR) != 0) return;
765   super.setImage (image);
766   if (imageHandle == 0) return;
767   if (image != null) {
768     OS.gtk_image_set_from_pixmap (imageHandle, image.pixmap, image.mask);
769     OS.gtk_widget_show (imageHandle);
770   } else {
771     OS.gtk_image_set_from_pixmap (imageHandle, 0, 0);
772     OS.gtk_widget_hide (imageHandle);
773   }
774 }
775 
776 boolean setRadioSelection (boolean value) {
777   if ((style & SWT.RADIO) == 0) return false;
778   if (getSelection () != value) {
779     setSelection (value);
780     postEvent (SWT.Selection);
781   }
782   return true;
783 }
784 
785 /**
786  * Sets the selection state of the receiver.
787  * <p>
788  * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
789  * it is selected when it is checked (which some platforms draw as a
790  * pushed in button).
791  * </p>
792  *
793  * @param selected the new selection state
794  *
795  * @exception SWTException <ul>
796  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
797  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
798  * </ul>
799  */
800 public void setSelection (boolean selected) {
801   if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
802   if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
803   if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return;
804   OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CLICKED);
805   OS.gtk_toggle_button_set_active (handle, selected);
806   OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CLICKED);
807 }
808 
809 /**
810  * Sets the receiver's text. The string may include
811  * the mnemonic character.
812  * </p>
813  * <p>
814  * Mnemonics are indicated by an '&amp' that causes the next
815  * character to be the mnemonic.  When the user presses a
816  * key sequence that matches the mnemonic, a selection
817  * event occurs. On most platforms, the mnemonic appears
818  * underlined but may be emphasised in a platform specific
819  * manner.  The mnemonic indicator character '&amp' can be
820  * escaped by doubling it in the string, causing a single
821  *'&amp' to be displayed.
822  * </p>
823  * 
824  * @param string the new text
825  *
826  * @exception IllegalArgumentException <ul>
827  *    <li>ERROR_NULL_ARGUMENT - if the text is null</li>
828  * </ul>
829  * @exception SWTException <ul>
830  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
831  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
832  * </ul>
833  */
834 public void setText (String string) {
835   checkWidget();
836   if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
837   if ((style & SWT.SEPARATOR) != 0) return;
838   super.setText (string);
839   if (labelHandle == 0) return;
840   char [] chars = fixMnemonic (string);
841   byte [] buffer = Converter.wcsToMbcs (null, chars, true);
842   OS.gtk_label_set_text_with_mnemonic (labelHandle, buffer);
843   if (string.length () != 0) {
844     OS.gtk_widget_show (labelHandle);
845   } else {
846     OS.gtk_widget_hide (labelHandle);
847   }
848 }
849 
850 /**
851  * Sets the receiver's tool tip text to the argument, which
852  * may be null indicating that no tool tip text should be shown.
853  *
854  * @param string the new tool tip text (or null)
855  *
856  * @exception SWTException <ul>
857  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
858  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
859  * </ul>
860  */
861 public void setToolTipText (String string) {
862   checkWidget();
863   toolTipText = string;
864   if (parent.toolTipText == null) {
865     Shell shell = parent._getShell ();
866     shell.setToolTipText (handle, toolTipText);
867   }
868 }
869 
870 /**
871  * Sets the width of the receiver.
872  *
873  * @param width the new width
874  *
875  * @exception SWTException <ul>
876  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
877  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
878  * </ul>
879  */
880 public void setWidth (int width) {
881   checkWidget();
882   if ((style & SWT.SEPARATOR) == 0) return;
883   if (width < 0) return;
884   OS.gtk_widget_set_size_request (handle, width, -1);
885   /*
886   * Force the container to allocate the size of its children.
887   */
888   long /*int*/ parentHandle = parent.parentingHandle ();
889   OS.gtk_container_resize_children (parentHandle);
890   if (control != null && !control.isDisposed ()) {
891     OS.gtk_widget_reparent (control.topHandle(), parentHandle);
892     control.setBounds (getBounds ());
893     OS.gtk_widget_reparent (control.topHandle(), handle);
894   }
895 }
896 
897 static int checkStyle (int style) {
898   return checkBits (style, SWT.PUSH, SWT.CHECK, SWT.RADIO, SWT.SEPARATOR, SWT.DROP_DOWN, 0);
899 }
900 }