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 '&' 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 '&' can be
820 * escaped by doubling it in the string, causing a single
821 *'&' 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 }