KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > swt > widgets > ToolItem


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-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.win32.*;
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
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     ToolBar parent;
38     Control control;
39     String JavaDoc toolTipText;
40     Image disabledImage, hotImage;
41     Image disabledImage2;
42     int id;
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     parent.createItem (this, 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 zero-relative 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  * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
106  * </ul>
107  * @exception SWTException <ul>
108  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
109  * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
110  * </ul>
111  *
112  * @see SWT#PUSH
113  * @see SWT#CHECK
114  * @see SWT#RADIO
115  * @see SWT#SEPARATOR
116  * @see SWT#DROP_DOWN
117  * @see Widget#checkSubclass
118  * @see Widget#getStyle
119  */

120 public ToolItem (ToolBar parent, int style, int index) {
121     super (parent, checkStyle (style));
122     this.parent = parent;
123     parent.createItem (this, index);
124 }
125
126 /**
127  * Adds the listener to the collection of listeners who will
128  * be notified when the control is selected by the user, by sending
129  * it one of the messages defined in the <code>SelectionListener</code>
130  * interface.
131  * <p>
132  * When <code>widgetSelected</code> is called when the mouse is over the arrow portion of a drop-down tool,
133  * the event object detail field contains the value <code>SWT.ARROW</code>.
134  * <code>widgetDefaultSelected</code> is not called.
135  * </p>
136  *
137  * @param listener the listener which should be notified when the control is selected by the user,
138  *
139  * @exception IllegalArgumentException <ul>
140  * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
141  * </ul>
142  * @exception SWTException <ul>
143  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
144  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
145  * </ul>
146  *
147  * @see SelectionListener
148  * @see #removeSelectionListener
149  * @see SelectionEvent
150  */

151 public void addSelectionListener(SelectionListener listener) {
152     checkWidget();
153     if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
154     TypedListener typedListener = new TypedListener (listener);
155     addListener (SWT.Selection,typedListener);
156     addListener (SWT.DefaultSelection,typedListener);
157 }
158
159 static int checkStyle (int style) {
160     return checkBits (style, SWT.PUSH, SWT.CHECK, SWT.RADIO, SWT.SEPARATOR, SWT.DROP_DOWN, 0);
161 }
162
163 protected void checkSubclass () {
164     if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
165 }
166
167 void click (boolean dropDown) {
168     int hwnd = parent.handle;
169     if (OS.GetKeyState (OS.VK_LBUTTON) < 0) return;
170     int index = OS.SendMessage (hwnd, OS.TB_COMMANDTOINDEX, id, 0);
171     RECT rect = new RECT ();
172     OS.SendMessage (hwnd, OS.TB_GETITEMRECT, index, rect);
173     int hotIndex = OS.SendMessage (hwnd, OS.TB_GETHOTITEM, 0, 0);
174     
175     /*
176     * In order to emulate all the processing that
177     * happens when a mnemonic key is pressed, fake
178     * a mouse press and release. This will ensure
179     * that radio and pull down items are handled
180     * properly.
181     */

182     int y = rect.top + (rect.bottom - rect.top) / 2;
183     int lParam = ((dropDown ? rect.right - 1 : rect.left) & 0xFFFF) | ((y << 16) & 0xFFFF0000);
184     parent.ignoreMouse = true;
185     OS.SendMessage (hwnd, OS.WM_LBUTTONDOWN, 0, lParam);
186     OS.SendMessage (hwnd, OS.WM_LBUTTONUP, 0, lParam);
187     parent.ignoreMouse = false;
188     
189     if (hotIndex != -1) {
190         OS.SendMessage (hwnd, OS.TB_SETHOTITEM, hotIndex, 0);
191     }
192 }
193
194 void destroyWidget () {
195     parent.destroyItem (this);
196     releaseHandle ();
197 }
198
199 /**
200  * Returns a rectangle describing the receiver's size and location
201  * relative to its parent.
202  *
203  * @return the receiver's bounding rectangle
204  *
205  * @exception SWTException <ul>
206  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
207  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
208  * </ul>
209  */

210 public Rectangle getBounds () {
211     checkWidget();
212     int hwnd = parent.handle;
213     int index = OS.SendMessage (hwnd, OS.TB_COMMANDTOINDEX, id, 0);
214     RECT rect = new RECT ();
215     OS.SendMessage (hwnd, OS.TB_GETITEMRECT, index, rect);
216     int width = rect.right - rect.left;
217     int height = rect.bottom - rect.top;
218     return new Rectangle (rect.left, rect.top, width, height);
219 }
220
221 /**
222  * Returns the control that is used to fill the bounds of
223  * the item when the item is a <code>SEPARATOR</code>.
224  *
225  * @return the control
226  *
227  * @exception SWTException <ul>
228  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
229  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
230  * </ul>
231  */

232 public Control getControl () {
233     checkWidget();
234     return control;
235 }
236
237 /**
238  * Returns the receiver's disabled image if it has one, or null
239  * if it does not.
240  * <p>
241  * The disabled image is displayed when the receiver is disabled.
242  * </p>
243  *
244  * @return the receiver's disabled image
245  *
246  * @exception SWTException <ul>
247  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
248  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
249  * </ul>
250  */

251 public Image getDisabledImage () {
252     checkWidget();
253     return disabledImage;
254 }
255
256 /**
257  * Returns <code>true</code> if the receiver is enabled, and
258  * <code>false</code> otherwise. A disabled control is typically
259  * not selectable from the user interface and draws with an
260  * inactive or "grayed" look.
261  *
262  * @return the receiver's enabled state
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  * @see #isEnabled
270  */

271 public boolean getEnabled () {
272     checkWidget();
273     if ((style & SWT.SEPARATOR) != 0) {
274         return (state & DISABLED) == 0;
275     }
276     int hwnd = parent.handle;
277     int fsState = OS.SendMessage (hwnd, OS.TB_GETSTATE, id, 0);
278     return (fsState & OS.TBSTATE_ENABLED) != 0;
279 }
280
281 /**
282  * Returns the receiver's hot image if it has one, or null
283  * if it does not.
284  * <p>
285  * The hot image is displayed when the mouse enters the receiver.
286  * </p>
287  *
288  * @return the receiver's hot 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 getHotImage () {
296     checkWidget();
297     return hotImage;
298 }
299
300 /**
301  * Returns the receiver's parent, which must be a <code>ToolBar</code>.
302  *
303  * @return the receiver's parent
304  *
305  * @exception SWTException <ul>
306  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
307  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
308  * </ul>
309  */

310 public ToolBar getParent () {
311     checkWidget();
312     return parent;
313 }
314
315 /**
316  * Returns <code>true</code> if the receiver is selected,
317  * and false otherwise.
318  * <p>
319  * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
320  * it is selected when it is checked (which some platforms draw as a
321  * pushed in button). If the receiver is of any other type, this method
322  * returns false.
323  * </p>
324  *
325  * @return the selection state
326  *
327  * @exception SWTException <ul>
328  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
329  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
330  * </ul>
331  */

332 public boolean getSelection () {
333     checkWidget();
334     if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return false;
335     int hwnd = parent.handle;
336     int fsState = OS.SendMessage (hwnd, OS.TB_GETSTATE, id, 0);
337     return (fsState & OS.TBSTATE_CHECKED) != 0;
338 }
339
340 /**
341  * Returns the receiver's tool tip text, or null if it has not been set.
342  *
343  * @return the receiver's tool tip text
344  *
345  * @exception SWTException <ul>
346  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
347  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
348  * </ul>
349  */

350 public String JavaDoc getToolTipText () {
351     checkWidget();
352     return toolTipText;
353 }
354
355 /**
356  * Gets the width of the receiver.
357  *
358  * @return the width
359  *
360  * @exception SWTException <ul>
361  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
362  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
363  * </ul>
364  */

365 public int getWidth () {
366     checkWidget();
367     int hwnd = parent.handle;
368     int index = OS.SendMessage (hwnd, OS.TB_COMMANDTOINDEX, id, 0);
369     RECT rect = new RECT ();
370     OS.SendMessage (hwnd, OS.TB_GETITEMRECT, index, rect);
371     return rect.right - rect.left;
372 }
373
374 /**
375  * Returns <code>true</code> if the receiver is enabled and all
376  * of the receiver's ancestors are enabled, and <code>false</code>
377  * otherwise. A disabled control is typically not selectable from the
378  * user interface and draws with an inactive or "grayed" look.
379  *
380  * @return the receiver's enabled state
381  *
382  * @exception SWTException <ul>
383  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
384  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
385  * </ul>
386  *
387  * @see #getEnabled
388  */

389 public boolean isEnabled () {
390     checkWidget();
391     return getEnabled () && parent.isEnabled ();
392 }
393
394 void releaseWidget () {
395     super.releaseWidget ();
396     releaseImages ();
397     control = null;
398     toolTipText = null;
399     disabledImage = hotImage = null;
400     if (disabledImage2 != null) disabledImage2.dispose ();
401     disabledImage2 = null;
402 }
403
404 void releaseHandle () {
405     super.releaseHandle ();
406     parent = null;
407     id = -1;
408 }
409
410 void releaseImages () {
411     TBBUTTONINFO info = new TBBUTTONINFO ();
412     info.cbSize = TBBUTTONINFO.sizeof;
413     info.dwMask = OS.TBIF_IMAGE | OS.TBIF_STYLE;
414     int hwnd = parent.handle;
415     OS.SendMessage (hwnd, OS.TB_GETBUTTONINFO, id, info);
416     /*
417     * Feature in Windows. For some reason, a tool item that has
418     * the style BTNS_SEP does not return I_IMAGENONE when queried
419     * for an image index, despite the fact that no attempt has been
420     * made to assign an image to the item. As a result, operations
421     * on an image list that use the wrong index cause random results.
422     * The fix is to ensure that the tool item is not a separator
423     * before using the image index. Since separators cannot have
424     * an image and one is never assigned, this is not a problem.
425     */

426     if ((info.fsStyle & OS.BTNS_SEP) == 0 && info.iImage != OS.I_IMAGENONE) {
427         ImageList imageList = parent.getImageList ();
428         ImageList hotImageList = parent.getHotImageList ();
429         ImageList disabledImageList = parent.getDisabledImageList();
430         if (imageList != null) imageList.put (info.iImage, null);
431         if (hotImageList != null) hotImageList.put (info.iImage, null);
432         if (disabledImageList != null) disabledImageList.put (info.iImage, null);
433     }
434 }
435
436 /**
437  * Removes the listener from the collection of listeners who will
438  * be notified when the control is selected by the user.
439  *
440  * @param listener the listener which should no longer be notified
441  *
442  * @exception IllegalArgumentException <ul>
443  * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
444  * </ul>
445  * @exception SWTException <ul>
446  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
447  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
448  * </ul>
449  *
450  * @see SelectionListener
451  * @see #addSelectionListener
452  */

453 public void removeSelectionListener(SelectionListener listener) {
454     checkWidget();
455     if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
456     if (eventTable == null) return;
457     eventTable.unhook (SWT.Selection, listener);
458     eventTable.unhook (SWT.DefaultSelection,listener);
459 }
460
461 void resizeControl () {
462     if (control != null && !control.isDisposed ()) {
463         /*
464         * Set the size and location of the control
465         * separately to minimize flashing in the
466         * case where the control does not resize
467         * to the size that was requested. This
468         * case can occur when the control is a
469         * combo box.
470         */

471         Rectangle itemRect = getBounds ();
472         control.setSize (itemRect.width, itemRect.height);
473         Rectangle rect = control.getBounds ();
474         rect.x = itemRect.x + (itemRect.width - rect.width) / 2;
475         rect.y = itemRect.y + (itemRect.height - rect.height) / 2;
476         control.setLocation (rect.x, rect.y);
477     }
478 }
479
480 void selectRadio () {
481     int index = 0;
482     ToolItem [] items = parent.getItems ();
483     while (index < items.length && items [index] != this) index++;
484     int i = index - 1;
485     while (i >= 0 && items [i].setRadioSelection (false)) --i;
486     int j = index + 1;
487     while (j < items.length && items [j].setRadioSelection (false)) j++;
488     setSelection (true);
489 }
490
491 /**
492  * Sets the control that is used to fill the bounds of
493  * the item when the item is a <code>SEPARATOR</code>.
494  *
495  * @param control the new control
496  *
497  * @exception IllegalArgumentException <ul>
498  * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
499  * <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</li>
500  * </ul>
501  * @exception SWTException <ul>
502  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
503  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
504  * </ul>
505  */

506 public void setControl (Control control) {
507     checkWidget();
508     if (control != null) {
509         if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
510         if (control.parent != parent) error (SWT.ERROR_INVALID_PARENT);
511     }
512     if ((style & SWT.SEPARATOR) == 0) return;
513     this.control = control;
514     /*
515     * Feature in Windows. When a tool bar wraps, tool items
516     * with the style BTNS_SEP are used as wrap points. This
517     * means that controls that are placed on top of separator
518     * items are not positioned properly. Also, vertical tool
519     * bars are implemented using TB_SETROWS to set the number
520     * of rows. When a control is placed on top of a separator,
521     * the height of the separator does not grow. The fix in
522     * both cases is to change the tool item style from BTNS_SEP
523     * to BTNS_BUTTON, causing the item to wrap like a tool item
524     * button. The new tool item button is disabled to avoid key
525     * traversal and the image is set to I_IMAGENONE to avoid
526     * getting the first image from the image list.
527     */

528     if ((parent.style & (SWT.WRAP | SWT.VERTICAL)) != 0) {
529         boolean changed = false;
530         int hwnd = parent.handle;
531         TBBUTTONINFO info = new TBBUTTONINFO ();
532         info.cbSize = TBBUTTONINFO.sizeof;
533         info.dwMask = OS.TBIF_STYLE | OS.TBIF_STATE;
534         OS.SendMessage (hwnd, OS.TB_GETBUTTONINFO, id, info);
535         if (control == null) {
536             if ((info.fsStyle & OS.BTNS_SEP) == 0) {
537                 changed = true;
538                 info.fsStyle &= ~OS.BTNS_BUTTON;
539                 info.fsStyle |= OS.BTNS_SEP;
540                 if ((state & DISABLED) != 0) {
541                     info.fsState &= ~OS.TBSTATE_ENABLED;
542                 } else {
543                     info.fsState |= OS.TBSTATE_ENABLED;
544                 }
545             }
546         } else {
547             if ((info.fsStyle & OS.BTNS_SEP) != 0) {
548                 changed = true;
549                 info.fsStyle &= ~OS.BTNS_SEP;
550                 info.fsStyle |= OS.BTNS_BUTTON;
551                 info.fsState &= ~OS.TBSTATE_ENABLED;
552                 info.dwMask |= OS.TBIF_IMAGE;
553                 info.iImage = OS.I_IMAGENONE;
554             }
555         }
556         if (changed) {
557             OS.SendMessage (hwnd, OS.TB_SETBUTTONINFO, id, info);
558             /*
559             * Bug in Windows. When TB_SETBUTTONINFO changes the
560             * style of a tool item from BTNS_SEP to BTNS_BUTTON
561             * and the tool bar is wrapped, the tool bar does not
562             * redraw properly. Windows uses separator items as
563             * wrap points and sometimes draws etching above or
564             * below and entire row. The fix is to redraw the
565             * tool bar.
566             */

567             if (OS.SendMessage (hwnd, OS.TB_GETROWS, 0, 0) > 1) {
568                 OS.InvalidateRect (hwnd, null, true);
569             }
570         }
571     }
572     resizeControl ();
573 }
574
575 /**
576  * Enables the receiver if the argument is <code>true</code>,
577  * and disables it otherwise.
578  * <p>
579  * A disabled control is typically
580  * not selectable from the user interface and draws with an
581  * inactive or "grayed" look.
582  * </p>
583  *
584  * @param enabled the new enabled state
585  *
586  * @exception SWTException <ul>
587  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
588  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
589  * </ul>
590  */

591 public void setEnabled (boolean enabled) {
592     checkWidget();
593     int hwnd = parent.handle;
594     int fsState = OS.SendMessage (hwnd, OS.TB_GETSTATE, id, 0);
595     /*
596     * Feature in Windows. When TB_SETSTATE is used to set the
597     * state of a tool item, the item redraws even when the state
598     * has not changed. The fix is to detect this case and avoid
599     * setting the state.
600     */

601     if (((fsState & OS.TBSTATE_ENABLED) != 0) == enabled) return;
602     if (enabled) {
603         fsState |= OS.TBSTATE_ENABLED;
604         state &= ~DISABLED;
605     } else {
606         fsState &= ~OS.TBSTATE_ENABLED;
607         state |= DISABLED;
608     }
609     OS.SendMessage (hwnd, OS.TB_SETSTATE, id, fsState);
610     if ((style & SWT.SEPARATOR) == 0) {
611         if (image != null) updateImages (enabled && parent.getEnabled ());
612     }
613 }
614
615 /**
616  * Sets the receiver's disabled image to the argument, which may be
617  * null indicating that no disabled image should be displayed.
618  * <p>
619  * The disabled image is displayed when the receiver is disabled.
620  * </p>
621  *
622  * @param image the disabled image to display on the receiver (may be null)
623  *
624  * @exception IllegalArgumentException <ul>
625  * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
626  * </ul>
627  * @exception SWTException <ul>
628  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
629  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
630  * </ul>
631  */

632 public void setDisabledImage (Image image) {
633     checkWidget();
634     if ((style & SWT.SEPARATOR) != 0) return;
635     if (image != null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
636     disabledImage = image;
637     updateImages (getEnabled () && parent.getEnabled ());
638 }
639
640 /**
641  * Sets the receiver's hot image to the argument, which may be
642  * null indicating that no hot image should be displayed.
643  * <p>
644  * The hot image is displayed when the mouse enters the receiver.
645  * </p>
646  *
647  * @param image the hot image to display on the receiver (may be null)
648  *
649  * @exception IllegalArgumentException <ul>
650  * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
651  * </ul>
652  * @exception SWTException <ul>
653  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
654  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
655  * </ul>
656  */

657 public void setHotImage (Image image) {
658     checkWidget();
659     if ((style & SWT.SEPARATOR) != 0) return;
660     if (image != null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
661     hotImage = image;
662     updateImages (getEnabled () && parent.getEnabled ());
663 }
664
665 public void setImage (Image image) {
666     checkWidget();
667     if ((style & SWT.SEPARATOR) != 0) return;
668     if (image != null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
669     super.setImage (image);
670     updateImages (getEnabled () && parent.getEnabled ());
671 }
672
673 boolean setRadioSelection (boolean value) {
674     if ((style & SWT.RADIO) == 0) return false;
675     if (getSelection () != value) {
676         setSelection (value);
677         postEvent (SWT.Selection);
678     }
679     return true;
680 }
681
682 /**
683  * Sets the selection state of the receiver.
684  * <p>
685  * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
686  * it is selected when it is checked (which some platforms draw as a
687  * pushed in button).
688  * </p>
689  *
690  * @param selected the new selection state
691  *
692  * @exception SWTException <ul>
693  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
694  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
695  * </ul>
696  */

697 public void setSelection (boolean selected) {
698     checkWidget();
699     if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return;
700     int hwnd = parent.handle;
701     int fsState = OS.SendMessage (hwnd, OS.TB_GETSTATE, id, 0);
702     /*
703     * Feature in Windows. When TB_SETSTATE is used to set the
704     * state of a tool item, the item redraws even when the state
705     * has not changed. The fix is to detect this case and avoid
706     * setting the state.
707     */

708     if (((fsState & OS.TBSTATE_CHECKED) != 0) == selected) return;
709     if (selected) {
710         fsState |= OS.TBSTATE_CHECKED;
711     } else {
712         fsState &= ~OS.TBSTATE_CHECKED;
713     }
714     OS.SendMessage (hwnd, OS.TB_SETSTATE, id, fsState);
715     
716     /*
717     * Bug in Windows. When a tool item with the style
718     * BTNS_CHECK or BTNS_CHECKGROUP is selected and then
719     * disabled, the item does not draw using the disabled
720     * image. The fix is to use the disabled image in all
721     * image lists for the item.
722     *
723     * NOTE: This means that the image list must be updated
724     * when the selection changes in a disabled tool item.
725     */

726     if ((style & (SWT.CHECK | SWT.RADIO)) != 0) {
727         if (!getEnabled () || !parent.getEnabled ()) {
728             updateImages (false);
729         }
730     }
731 }
732
733 /**
734  * Sets the receiver's text. The string may include
735  * the mnemonic character.
736  * </p>
737  * <p>
738  * Mnemonics are indicated by an '&amp;' that causes the next
739  * character to be the mnemonic. When the user presses a
740  * key sequence that matches the mnemonic, a selection
741  * event occurs. On most platforms, the mnemonic appears
742  * underlined but may be emphasised in a platform specific
743  * manner. The mnemonic indicator character '&amp;' can be
744  * escaped by doubling it in the string, causing a single
745  * '&amp;' to be displayed.
746  * </p>
747  *
748  * @param string the new text
749  *
750  * @exception IllegalArgumentException <ul>
751  * <li>ERROR_NULL_ARGUMENT - if the text is null</li>
752  * </ul>
753  * @exception SWTException <ul>
754  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
755  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
756  * </ul>
757  */

758 public void setText (String JavaDoc string) {
759     checkWidget();
760     if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
761     if ((style & SWT.SEPARATOR) != 0) return;
762     if (string.equals (text)) return;
763     super.setText (string);
764     int hwnd = parent.handle;
765     TBBUTTONINFO info = new TBBUTTONINFO ();
766     info.cbSize = TBBUTTONINFO.sizeof;
767     info.dwMask = OS.TBIF_TEXT | OS.TBIF_STYLE;
768     info.fsStyle = (byte) (widgetStyle () | OS.BTNS_AUTOSIZE);
769     int hHeap = OS.GetProcessHeap (), pszText = 0;
770     if (string.length () != 0) {
771         info.fsStyle |= OS.BTNS_SHOWTEXT;
772         TCHAR buffer = new TCHAR (parent.getCodePage (), string, true);
773         int byteCount = buffer.length () * TCHAR.sizeof;
774         pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
775         OS.MoveMemory (pszText, buffer, byteCount);
776         info.pszText = pszText;
777     }
778     OS.SendMessage (hwnd, OS.TB_SETBUTTONINFO, id, info);
779     if (pszText != 0) OS.HeapFree (hHeap, 0, pszText);
780     
781     /*
782     * Bug in Windows. For some reason, when the font is set
783     * before any tool item has text, the tool items resize to
784     * a very small size. Also, a tool item will only show text
785     * when text has already been set on one item and then a new
786     * item is created. The fix is to use WM_SETFONT to force
787     * the tool bar to redraw and layout.
788     */

789     parent.setDropDownItems (false);
790     int hFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
791     OS.SendMessage (hwnd, OS.WM_SETFONT, hFont, 0);
792     parent.setDropDownItems (true);
793     parent.layoutItems ();
794 }
795
796 /**
797  * Sets the receiver's tool tip text to the argument, which
798  * may be null indicating that no tool tip text should be shown.
799  *
800  * @param string the new tool tip text (or null)
801  *
802  * @exception SWTException <ul>
803  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
804  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
805  * </ul>
806  */

807 public void setToolTipText (String JavaDoc string) {
808     checkWidget();
809     toolTipText = string;
810 }
811
812 /**
813  * Sets the width of the receiver, for <code>SEPARATOR</code> ToolItems.
814  *
815  * @param width the new width
816  *
817  * @exception SWTException <ul>
818  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
819  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
820  * </ul>
821  */

822 public void setWidth (int width) {
823     checkWidget();
824     if ((style & SWT.SEPARATOR) == 0) return;
825     if (width < 0) return;
826     int hwnd = parent.handle;
827     TBBUTTONINFO info = new TBBUTTONINFO ();
828     info.cbSize = TBBUTTONINFO.sizeof;
829     info.dwMask = OS.TBIF_SIZE;
830     info.cx = (short) width;
831     OS.SendMessage (hwnd, OS.TB_SETBUTTONINFO, id, info);
832     parent.layoutItems ();
833 }
834
835 void updateImages (boolean enabled) {
836     if ((style & SWT.SEPARATOR) != 0) return;
837     int hwnd = parent.handle;
838     TBBUTTONINFO info = new TBBUTTONINFO ();
839     info.cbSize = TBBUTTONINFO.sizeof;
840     info.dwMask = OS.TBIF_IMAGE;
841     OS.SendMessage (hwnd, OS.TB_GETBUTTONINFO, id, info);
842     if (info.iImage == OS.I_IMAGENONE && image == null) return;
843     ImageList imageList = parent.getImageList ();
844     ImageList hotImageList = parent.getHotImageList ();
845     ImageList disabledImageList = parent.getDisabledImageList();
846     if (info.iImage == OS.I_IMAGENONE) {
847         Rectangle bounds = image.getBounds ();
848         int listStyle = parent.style & SWT.RIGHT_TO_LEFT;
849         if (imageList == null) {
850             imageList = display.getImageListToolBar (listStyle, bounds.width, bounds.height);
851         }
852         if (disabledImageList == null) {
853             disabledImageList = display.getImageListToolBarDisabled (listStyle, bounds.width, bounds.height);
854         }
855         if (hotImageList == null) {
856             hotImageList = display.getImageListToolBarHot (listStyle, bounds.width, bounds.height);
857         }
858         Image disabled = disabledImage;
859         if (disabledImage == null) {
860             if (disabledImage2 != null) disabledImage2.dispose ();
861             disabledImage2 = null;
862             disabled = image;
863             if (!enabled) {
864                 disabled = disabledImage2 = new Image (display, image, SWT.IMAGE_DISABLE);
865             }
866         }
867         /*
868         * Bug in Windows. When a tool item with the style
869         * BTNS_CHECK or BTNS_CHECKGROUP is selected and then
870         * disabled, the item does not draw using the disabled
871         * image. The fix is to assign the disabled image in
872         * all image lists.
873         */

874         Image image2 = image, hot = hotImage;
875         if ((style & (SWT.CHECK | SWT.RADIO)) != 0) {
876             if (!enabled) image2 = hot = disabled;
877         }
878         info.iImage = imageList.add (image2);
879         disabledImageList.add (disabled);
880         hotImageList.add (hot != null ? hot : image2);
881         parent.setImageList (imageList);
882         parent.setDisabledImageList (disabledImageList);
883         parent.setHotImageList (hotImageList);
884     } else {
885         Image disabled = null;
886         if (disabledImageList != null) {
887             if (image != null) {
888                 if (disabledImage2 != null) disabledImage2.dispose ();
889                 disabledImage2 = null;
890                 disabled = disabledImage;
891                 if (disabledImage == null) {
892                     disabled = image;
893                     if (!enabled) {
894                         disabled = disabledImage2 = new Image (display, image, SWT.IMAGE_DISABLE);
895                     }
896                 }
897             }
898             disabledImageList.put (info.iImage, disabled);
899         }
900         /*
901         * Bug in Windows. When a tool item with the style
902         * BTNS_CHECK or BTNS_CHECKGROUP is selected and then
903         * disabled, the item does not draw using the disabled
904         * image. The fix is to use the disabled image in all
905         * image lists.
906         */

907         Image image2 = image, hot = hotImage;
908         if ((style & (SWT.CHECK | SWT.RADIO)) != 0) {
909             if (!enabled) image2 = hot = disabled;
910         }
911         if (imageList != null) imageList.put (info.iImage, image2);
912         if (hotImageList != null) {
913             hotImageList.put (info.iImage, hot != null ? hot : image2);
914         }
915         if (image == null) info.iImage = OS.I_IMAGENONE;
916     }
917
918     /*
919     * Bug in Windows. If the width of an item has already been
920     * calculated, the tool bar control will not recalculate it to
921     * include the space for the image. The fix is to set the width
922     * to zero, forcing the control recalculate the width for the item.
923     */

924     info.dwMask |= OS.TBIF_SIZE;
925     info.cx = 0;
926     OS.SendMessage (hwnd, OS.TB_SETBUTTONINFO, id, info);
927     
928     parent.layoutItems ();
929 }
930
931 int widgetStyle () {
932     if ((style & SWT.DROP_DOWN) != 0) return OS.BTNS_DROPDOWN;
933     if ((style & SWT.PUSH) != 0) return OS.BTNS_BUTTON;
934     if ((style & SWT.CHECK) != 0) return OS.BTNS_CHECK;
935     /*
936     * This code is intentionally commented. In order to
937     * consistently support radio tool items across platforms,
938     * the platform radio behavior is not used.
939     */

940 // if ((style & SWT.RADIO) != 0) return OS.BTNS_CHECKGROUP;
941
if ((style & SWT.RADIO) != 0) return OS.BTNS_CHECK;
942     if ((style & SWT.SEPARATOR) != 0) return OS.BTNS_SEP;
943     return OS.BTNS_BUTTON;
944 }
945
946 LRESULT wmCommandChild (int wParam, int lParam) {
947     if ((style & SWT.RADIO) != 0) {
948         if ((parent.getStyle () & SWT.NO_RADIO_GROUP) == 0) {
949             selectRadio ();
950         }
951     }
952     postEvent (SWT.Selection);
953     return null;
954 }
955
956 }
957
Popular Tags