Mercurial > projects > dwt2
comparison org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ToolItem.d @ 0:6dd524f61e62
add dwt win and basic java stuff
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Mon, 02 Mar 2009 14:44:16 +0100 |
parents | |
children | 2e09b0e6857a |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:6dd524f61e62 |
---|---|
1 /******************************************************************************* | |
2 * Copyright (c) 2000, 2008 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 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
12 *******************************************************************************/ | |
13 module org.eclipse.swt.widgets.ToolItem; | |
14 | |
15 import org.eclipse.swt.SWT; | |
16 import org.eclipse.swt.SWTException; | |
17 import org.eclipse.swt.events.SelectionEvent; | |
18 import org.eclipse.swt.events.SelectionListener; | |
19 import org.eclipse.swt.graphics.Image; | |
20 import org.eclipse.swt.graphics.Rectangle; | |
21 import org.eclipse.swt.internal.ImageList; | |
22 import org.eclipse.swt.internal.win32.OS; | |
23 | |
24 import org.eclipse.swt.widgets.Item; | |
25 import org.eclipse.swt.widgets.Widget; | |
26 import org.eclipse.swt.widgets.ToolBar; | |
27 import org.eclipse.swt.widgets.Control; | |
28 import org.eclipse.swt.widgets.TypedListener; | |
29 | |
30 import java.lang.all; | |
31 | |
32 | |
33 /** | |
34 * Instances of this class represent a selectable user interface object | |
35 * that represents a button in a tool bar. | |
36 * <dl> | |
37 * <dt><b>Styles:</b></dt> | |
38 * <dd>PUSH, CHECK, RADIO, SEPARATOR, DROP_DOWN</dd> | |
39 * <dt><b>Events:</b></dt> | |
40 * <dd>Selection</dd> | |
41 * </dl> | |
42 * <p> | |
43 * Note: Only one of the styles CHECK, PUSH, RADIO, SEPARATOR and DROP_DOWN | |
44 * may be specified. | |
45 * </p><p> | |
46 * IMPORTANT: This class is <em>not</em> intended to be subclassed. | |
47 * </p> | |
48 * | |
49 * @see <a href="http://www.eclipse.org/swt/snippets/#toolbar">ToolBar, ToolItem snippets</a> | |
50 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> | |
51 */ | |
52 public class ToolItem : Item { | |
53 ToolBar parent; | |
54 Control control; | |
55 String toolTipText; | |
56 Image disabledImage, hotImage; | |
57 Image disabledImage2; | |
58 int id; | |
59 | |
60 /** | |
61 * Constructs a new instance of this class given its parent | |
62 * (which must be a <code>ToolBar</code>) and a style value | |
63 * describing its behavior and appearance. The item is added | |
64 * to the end of the items maintained by its parent. | |
65 * <p> | |
66 * The style value is either one of the style constants defined in | |
67 * class <code>SWT</code> which is applicable to instances of this | |
68 * class, or must be built by <em>bitwise OR</em>'ing together | |
69 * (that is, using the <code>int</code> "|" operator) two or more | |
70 * of those <code>SWT</code> style constants. The class description | |
71 * lists the style constants that are applicable to the class. | |
72 * Style bits are also inherited from superclasses. | |
73 * </p> | |
74 * | |
75 * @param parent a composite control which will be the parent of the new instance (cannot be null) | |
76 * @param style the style of control to construct | |
77 * | |
78 * @exception IllegalArgumentException <ul> | |
79 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | |
80 * </ul> | |
81 * @exception SWTException <ul> | |
82 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
83 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
84 * </ul> | |
85 * | |
86 * @see SWT#PUSH | |
87 * @see SWT#CHECK | |
88 * @see SWT#RADIO | |
89 * @see SWT#SEPARATOR | |
90 * @see SWT#DROP_DOWN | |
91 * @see Widget#checkSubclass | |
92 * @see Widget#getStyle | |
93 */ | |
94 public this (ToolBar parent, int style) { | |
95 super (parent, checkStyle (style)); | |
96 this.parent = parent; | |
97 parent.createItem (this, parent.getItemCount ()); | |
98 } | |
99 | |
100 /** | |
101 * Constructs a new instance of this class given its parent | |
102 * (which must be a <code>ToolBar</code>), a style value | |
103 * describing its behavior and appearance, and the index | |
104 * at which to place it in the items maintained by its parent. | |
105 * <p> | |
106 * The style value is either one of the style constants defined in | |
107 * class <code>SWT</code> which is applicable to instances of this | |
108 * class, or must be built by <em>bitwise OR</em>'ing together | |
109 * (that is, using the <code>int</code> "|" operator) two or more | |
110 * of those <code>SWT</code> style constants. The class description | |
111 * lists the style constants that are applicable to the class. | |
112 * Style bits are also inherited from superclasses. | |
113 * </p> | |
114 * | |
115 * @param parent a composite control which will be the parent of the new instance (cannot be null) | |
116 * @param style the style of control to construct | |
117 * @param index the zero-relative index to store the receiver in its parent | |
118 * | |
119 * @exception IllegalArgumentException <ul> | |
120 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | |
121 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li> | |
122 * </ul> | |
123 * @exception SWTException <ul> | |
124 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
125 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
126 * </ul> | |
127 * | |
128 * @see SWT#PUSH | |
129 * @see SWT#CHECK | |
130 * @see SWT#RADIO | |
131 * @see SWT#SEPARATOR | |
132 * @see SWT#DROP_DOWN | |
133 * @see Widget#checkSubclass | |
134 * @see Widget#getStyle | |
135 */ | |
136 public this (ToolBar parent, int style, int index) { | |
137 super (parent, checkStyle (style)); | |
138 this.parent = parent; | |
139 parent.createItem (this, index); | |
140 } | |
141 | |
142 /** | |
143 * Adds the listener to the collection of listeners who will | |
144 * be notified when the control is selected by the user, by sending | |
145 * it one of the messages defined in the <code>SelectionListener</code> | |
146 * interface. | |
147 * <p> | |
148 * When <code>widgetSelected</code> is called when the mouse is over the arrow portion of a drop-down tool, | |
149 * the event object detail field contains the value <code>SWT.ARROW</code>. | |
150 * <code>widgetDefaultSelected</code> is not called. | |
151 * </p> | |
152 * | |
153 * @param listener the listener which should be notified when the control is selected by the user, | |
154 * | |
155 * @exception IllegalArgumentException <ul> | |
156 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> | |
157 * </ul> | |
158 * @exception SWTException <ul> | |
159 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
160 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
161 * </ul> | |
162 * | |
163 * @see SelectionListener | |
164 * @see #removeSelectionListener | |
165 * @see SelectionEvent | |
166 */ | |
167 public void addSelectionListener(SelectionListener listener) { | |
168 checkWidget(); | |
169 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); | |
170 TypedListener typedListener = new TypedListener (listener); | |
171 addListener (SWT.Selection,typedListener); | |
172 addListener (SWT.DefaultSelection,typedListener); | |
173 } | |
174 | |
175 static int checkStyle (int style) { | |
176 return checkBits (style, SWT.PUSH, SWT.CHECK, SWT.RADIO, SWT.SEPARATOR, SWT.DROP_DOWN, 0); | |
177 } | |
178 | |
179 override protected void checkSubclass () { | |
180 if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); | |
181 } | |
182 | |
183 void click (bool dropDown) { | |
184 auto hwnd = parent.handle; | |
185 if (OS.GetKeyState (OS.VK_LBUTTON) < 0) return; | |
186 int index = OS.SendMessage (hwnd, OS.TB_COMMANDTOINDEX, id, 0); | |
187 RECT rect; | |
188 OS.SendMessage (hwnd, OS.TB_GETITEMRECT, index, &rect); | |
189 int hotIndex = OS.SendMessage (hwnd, OS.TB_GETHOTITEM, 0, 0); | |
190 | |
191 /* | |
192 * In order to emulate all the processing that | |
193 * happens when a mnemonic key is pressed, fake | |
194 * a mouse press and release. This will ensure | |
195 * that radio and pull down items are handled | |
196 * properly. | |
197 */ | |
198 int y = rect.top + (rect.bottom - rect.top) / 2; | |
199 int /*long*/ lParam = OS.MAKELPARAM (dropDown ? rect.right - 1 : rect.left, y); | |
200 parent.ignoreMouse = true; | |
201 OS.SendMessage (hwnd, OS.WM_LBUTTONDOWN, 0, lParam); | |
202 OS.SendMessage (hwnd, OS.WM_LBUTTONUP, 0, lParam); | |
203 parent.ignoreMouse = false; | |
204 | |
205 if (hotIndex !is -1) { | |
206 OS.SendMessage (hwnd, OS.TB_SETHOTITEM, hotIndex, 0); | |
207 } | |
208 } | |
209 | |
210 override void destroyWidget () { | |
211 parent.destroyItem (this); | |
212 releaseHandle (); | |
213 } | |
214 | |
215 /** | |
216 * Returns a rectangle describing the receiver's size and location | |
217 * relative to its parent. | |
218 * | |
219 * @return the receiver's bounding rectangle | |
220 * | |
221 * @exception SWTException <ul> | |
222 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
223 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
224 * </ul> | |
225 */ | |
226 public Rectangle getBounds () { | |
227 checkWidget(); | |
228 auto hwnd = parent.handle; | |
229 int index = OS.SendMessage (hwnd, OS.TB_COMMANDTOINDEX, id, 0); | |
230 RECT rect; | |
231 OS.SendMessage (hwnd, OS.TB_GETITEMRECT, index, &rect); | |
232 int width = rect.right - rect.left; | |
233 int height = rect.bottom - rect.top; | |
234 return new Rectangle (rect.left, rect.top, width, height); | |
235 } | |
236 | |
237 /** | |
238 * Returns the control that is used to fill the bounds of | |
239 * the item when the item is a <code>SEPARATOR</code>. | |
240 * | |
241 * @return the control | |
242 * | |
243 * @exception SWTException <ul> | |
244 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
245 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
246 * </ul> | |
247 */ | |
248 public Control getControl () { | |
249 checkWidget(); | |
250 return control; | |
251 } | |
252 | |
253 /** | |
254 * Returns the receiver's disabled image if it has one, or null | |
255 * if it does not. | |
256 * <p> | |
257 * The disabled image is displayed when the receiver is disabled. | |
258 * </p> | |
259 * | |
260 * @return the receiver's disabled image | |
261 * | |
262 * @exception SWTException <ul> | |
263 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
264 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
265 * </ul> | |
266 */ | |
267 public Image getDisabledImage () { | |
268 checkWidget(); | |
269 return disabledImage; | |
270 } | |
271 | |
272 /** | |
273 * Returns <code>true</code> if the receiver is enabled, and | |
274 * <code>false</code> otherwise. A disabled control is typically | |
275 * not selectable from the user interface and draws with an | |
276 * inactive or "grayed" look. | |
277 * | |
278 * @return the receiver's enabled state | |
279 * | |
280 * @exception SWTException <ul> | |
281 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
282 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
283 * </ul> | |
284 * | |
285 * @see #isEnabled | |
286 */ | |
287 public bool getEnabled () { | |
288 checkWidget(); | |
289 if ((style & SWT.SEPARATOR) !is 0) { | |
290 return (state & DISABLED) is 0; | |
291 } | |
292 auto hwnd = parent.handle; | |
293 int /*long*/ fsState = OS.SendMessage (hwnd, OS.TB_GETSTATE, id, 0); | |
294 return (fsState & OS.TBSTATE_ENABLED) !is 0; | |
295 } | |
296 | |
297 /** | |
298 * Returns the receiver's hot image if it has one, or null | |
299 * if it does not. | |
300 * <p> | |
301 * The hot image is displayed when the mouse enters the receiver. | |
302 * </p> | |
303 * | |
304 * @return the receiver's hot image | |
305 * | |
306 * @exception SWTException <ul> | |
307 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
308 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
309 * </ul> | |
310 */ | |
311 public Image getHotImage () { | |
312 checkWidget(); | |
313 return hotImage; | |
314 } | |
315 | |
316 /** | |
317 * Returns the receiver's parent, which must be a <code>ToolBar</code>. | |
318 * | |
319 * @return the receiver's parent | |
320 * | |
321 * @exception SWTException <ul> | |
322 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
323 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
324 * </ul> | |
325 */ | |
326 public ToolBar getParent () { | |
327 checkWidget(); | |
328 return parent; | |
329 } | |
330 | |
331 /** | |
332 * Returns <code>true</code> if the receiver is selected, | |
333 * and false otherwise. | |
334 * <p> | |
335 * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>, | |
336 * it is selected when it is checked (which some platforms draw as a | |
337 * pushed in button). If the receiver is of any other type, this method | |
338 * returns false. | |
339 * </p> | |
340 * | |
341 * @return the selection state | |
342 * | |
343 * @exception SWTException <ul> | |
344 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
345 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
346 * </ul> | |
347 */ | |
348 public bool getSelection () { | |
349 checkWidget(); | |
350 if ((style & (SWT.CHECK | SWT.RADIO)) is 0) return false; | |
351 auto hwnd = parent.handle; | |
352 int /*long*/ fsState = OS.SendMessage (hwnd, OS.TB_GETSTATE, id, 0); | |
353 return (fsState & OS.TBSTATE_CHECKED) !is 0; | |
354 } | |
355 | |
356 /** | |
357 * Returns the receiver's tool tip text, or null if it has not been set. | |
358 * | |
359 * @return the receiver's tool tip text | |
360 * | |
361 * @exception SWTException <ul> | |
362 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
363 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
364 * </ul> | |
365 */ | |
366 public String getToolTipText () { | |
367 checkWidget(); | |
368 return toolTipText; | |
369 } | |
370 | |
371 /** | |
372 * Gets the width of the receiver. | |
373 * | |
374 * @return the width | |
375 * | |
376 * @exception SWTException <ul> | |
377 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
378 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
379 * </ul> | |
380 */ | |
381 public int getWidth () { | |
382 checkWidget(); | |
383 auto hwnd = parent.handle; | |
384 int index = OS.SendMessage (hwnd, OS.TB_COMMANDTOINDEX, id, 0); | |
385 RECT rect; | |
386 OS.SendMessage (hwnd, OS.TB_GETITEMRECT, index, &rect); | |
387 return rect.right - rect.left; | |
388 } | |
389 | |
390 /** | |
391 * Returns <code>true</code> if the receiver is enabled and all | |
392 * of the receiver's ancestors are enabled, and <code>false</code> | |
393 * otherwise. A disabled control is typically not selectable from the | |
394 * user interface and draws with an inactive or "grayed" look. | |
395 * | |
396 * @return the receiver's enabled state | |
397 * | |
398 * @exception SWTException <ul> | |
399 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
400 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
401 * </ul> | |
402 * | |
403 * @see #getEnabled | |
404 */ | |
405 public bool isEnabled () { | |
406 checkWidget(); | |
407 return getEnabled () && parent.isEnabled (); | |
408 } | |
409 | |
410 override void releaseWidget () { | |
411 super.releaseWidget (); | |
412 releaseImages (); | |
413 control = null; | |
414 toolTipText = null; | |
415 disabledImage = hotImage = null; | |
416 if (disabledImage2 !is null) disabledImage2.dispose (); | |
417 disabledImage2 = null; | |
418 } | |
419 | |
420 override void releaseHandle () { | |
421 super.releaseHandle (); | |
422 parent = null; | |
423 id = -1; | |
424 } | |
425 | |
426 void releaseImages () { | |
427 TBBUTTONINFO info; | |
428 info.cbSize = TBBUTTONINFO.sizeof; | |
429 info.dwMask = OS.TBIF_IMAGE | OS.TBIF_STYLE; | |
430 auto hwnd = parent.handle; | |
431 OS.SendMessage (hwnd, OS.TB_GETBUTTONINFO, id, &info); | |
432 /* | |
433 * Feature in Windows. For some reason, a tool item that has | |
434 * the style BTNS_SEP does not return I_IMAGENONE when queried | |
435 * for an image index, despite the fact that no attempt has been | |
436 * made to assign an image to the item. As a result, operations | |
437 * on an image list that use the wrong index cause random results. | |
438 * The fix is to ensure that the tool item is not a separator | |
439 * before using the image index. Since separators cannot have | |
440 * an image and one is never assigned, this is not a problem. | |
441 */ | |
442 if ((info.fsStyle & OS.BTNS_SEP) is 0 && info.iImage !is OS.I_IMAGENONE) { | |
443 ImageList imageList = parent.getImageList (); | |
444 ImageList hotImageList = parent.getHotImageList (); | |
445 ImageList disabledImageList = parent.getDisabledImageList(); | |
446 if (imageList !is null) imageList.put (info.iImage, null); | |
447 if (hotImageList !is null) hotImageList.put (info.iImage, null); | |
448 if (disabledImageList !is null) disabledImageList.put (info.iImage, null); | |
449 } | |
450 } | |
451 | |
452 /** | |
453 * Removes the listener from the collection of listeners who will | |
454 * be notified when the control is selected by the user. | |
455 * | |
456 * @param listener the listener which should no longer be notified | |
457 * | |
458 * @exception IllegalArgumentException <ul> | |
459 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> | |
460 * </ul> | |
461 * @exception SWTException <ul> | |
462 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
463 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
464 * </ul> | |
465 * | |
466 * @see SelectionListener | |
467 * @see #addSelectionListener | |
468 */ | |
469 public void removeSelectionListener(SelectionListener listener) { | |
470 checkWidget(); | |
471 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); | |
472 if (eventTable is null) return; | |
473 eventTable.unhook (SWT.Selection, listener); | |
474 eventTable.unhook (SWT.DefaultSelection,listener); | |
475 } | |
476 | |
477 void resizeControl () { | |
478 if (control !is null && !control.isDisposed ()) { | |
479 /* | |
480 * Set the size and location of the control | |
481 * separately to minimize flashing in the | |
482 * case where the control does not resize | |
483 * to the size that was requested. This | |
484 * case can occur when the control is a | |
485 * combo box. | |
486 */ | |
487 Rectangle itemRect = getBounds (); | |
488 control.setSize (itemRect.width, itemRect.height); | |
489 Rectangle rect = control.getBounds (); | |
490 rect.x = itemRect.x + (itemRect.width - rect.width) / 2; | |
491 rect.y = itemRect.y + (itemRect.height - rect.height) / 2; | |
492 control.setLocation (rect.x, rect.y); | |
493 } | |
494 } | |
495 | |
496 void selectRadio () { | |
497 int index = 0; | |
498 ToolItem [] items = parent.getItems (); | |
499 while (index < items.length && items [index] !is this) index++; | |
500 int i = index - 1; | |
501 while (i >= 0 && items [i].setRadioSelection (false)) --i; | |
502 int j = index + 1; | |
503 while (j < items.length && items [j].setRadioSelection (false)) j++; | |
504 setSelection (true); | |
505 } | |
506 | |
507 /** | |
508 * Sets the control that is used to fill the bounds of | |
509 * the item when the item is a <code>SEPARATOR</code>. | |
510 * | |
511 * @param control the new control | |
512 * | |
513 * @exception IllegalArgumentException <ul> | |
514 * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li> | |
515 * <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</li> | |
516 * </ul> | |
517 * @exception SWTException <ul> | |
518 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
519 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
520 * </ul> | |
521 */ | |
522 public void setControl (Control control) { | |
523 checkWidget(); | |
524 if (control !is null) { | |
525 if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT); | |
526 if (control.parent !is parent) error (SWT.ERROR_INVALID_PARENT); | |
527 } | |
528 if ((style & SWT.SEPARATOR) is 0) return; | |
529 this.control = control; | |
530 /* | |
531 * Feature in Windows. When a tool bar wraps, tool items | |
532 * with the style BTNS_SEP are used as wrap points. This | |
533 * means that controls that are placed on top of separator | |
534 * items are not positioned properly. Also, vertical tool | |
535 * bars are implemented using TB_SETROWS to set the number | |
536 * of rows. When a control is placed on top of a separator, | |
537 * the height of the separator does not grow. The fix in | |
538 * both cases is to change the tool item style from BTNS_SEP | |
539 * to BTNS_BUTTON, causing the item to wrap like a tool item | |
540 * button. The new tool item button is disabled to avoid key | |
541 * traversal and the image is set to I_IMAGENONE to avoid | |
542 * getting the first image from the image list. | |
543 */ | |
544 if ((parent.style & (SWT.WRAP | SWT.VERTICAL)) !is 0) { | |
545 bool changed = false; | |
546 auto hwnd = parent.handle; | |
547 TBBUTTONINFO info; | |
548 info.cbSize = TBBUTTONINFO.sizeof; | |
549 info.dwMask = OS.TBIF_STYLE | OS.TBIF_STATE; | |
550 OS.SendMessage (hwnd, OS.TB_GETBUTTONINFO, id, &info); | |
551 if (control is null) { | |
552 if ((info.fsStyle & OS.BTNS_SEP) is 0) { | |
553 changed = true; | |
554 info.fsStyle &= ~OS.BTNS_BUTTON; | |
555 info.fsStyle |= OS.BTNS_SEP; | |
556 if ((state & DISABLED) !is 0) { | |
557 info.fsState &= ~OS.TBSTATE_ENABLED; | |
558 } else { | |
559 info.fsState |= OS.TBSTATE_ENABLED; | |
560 } | |
561 } | |
562 } else { | |
563 if ((info.fsStyle & OS.BTNS_SEP) !is 0) { | |
564 changed = true; | |
565 info.fsStyle &= ~OS.BTNS_SEP; | |
566 info.fsStyle |= OS.BTNS_BUTTON; | |
567 info.fsState &= ~OS.TBSTATE_ENABLED; | |
568 info.dwMask |= OS.TBIF_IMAGE; | |
569 info.iImage = OS.I_IMAGENONE; | |
570 } | |
571 } | |
572 if (changed) { | |
573 OS.SendMessage (hwnd, OS.TB_SETBUTTONINFO, id, &info); | |
574 /* | |
575 * Bug in Windows. When TB_SETBUTTONINFO changes the | |
576 * style of a tool item from BTNS_SEP to BTNS_BUTTON | |
577 * and the tool bar is wrapped, the tool bar does not | |
578 * redraw properly. Windows uses separator items as | |
579 * wrap points and sometimes draws etching above or | |
580 * below and entire row. The fix is to redraw the | |
581 * tool bar. | |
582 */ | |
583 if (OS.SendMessage (hwnd, OS.TB_GETROWS, 0, 0) > 1) { | |
584 OS.InvalidateRect (hwnd, null, true); | |
585 } | |
586 } | |
587 } | |
588 resizeControl (); | |
589 } | |
590 | |
591 /** | |
592 * Enables the receiver if the argument is <code>true</code>, | |
593 * and disables it otherwise. | |
594 * <p> | |
595 * A disabled control is typically | |
596 * not selectable from the user interface and draws with an | |
597 * inactive or "grayed" look. | |
598 * </p> | |
599 * | |
600 * @param enabled the new enabled state | |
601 * | |
602 * @exception SWTException <ul> | |
603 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
604 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
605 * </ul> | |
606 */ | |
607 public void setEnabled (bool enabled) { | |
608 checkWidget(); | |
609 auto hwnd = parent.handle; | |
610 int fsState = OS.SendMessage (hwnd, OS.TB_GETSTATE, id, 0); | |
611 /* | |
612 * Feature in Windows. When TB_SETSTATE is used to set the | |
613 * state of a tool item, the item redraws even when the state | |
614 * has not changed. The fix is to detect this case and avoid | |
615 * setting the state. | |
616 */ | |
617 if (((fsState & OS.TBSTATE_ENABLED) !is 0) is enabled) return; | |
618 if (enabled) { | |
619 fsState |= OS.TBSTATE_ENABLED; | |
620 state &= ~DISABLED; | |
621 } else { | |
622 fsState &= ~OS.TBSTATE_ENABLED; | |
623 state |= DISABLED; | |
624 } | |
625 OS.SendMessage (hwnd, OS.TB_SETSTATE, id, fsState); | |
626 if ((style & SWT.SEPARATOR) is 0) { | |
627 if (image !is null) updateImages (enabled && parent.getEnabled ()); | |
628 } | |
629 } | |
630 | |
631 /** | |
632 * Sets the receiver's disabled image to the argument, which may be | |
633 * null indicating that no disabled image should be displayed. | |
634 * <p> | |
635 * The disabled image is displayed when the receiver is disabled. | |
636 * </p> | |
637 * | |
638 * @param image the disabled image to display on the receiver (may be null) | |
639 * | |
640 * @exception IllegalArgumentException <ul> | |
641 * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</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 setDisabledImage (Image image) { | |
649 checkWidget(); | |
650 if ((style & SWT.SEPARATOR) !is 0) return; | |
651 if (image !is null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); | |
652 disabledImage = image; | |
653 updateImages (getEnabled () && parent.getEnabled ()); | |
654 } | |
655 | |
656 /** | |
657 * Sets the receiver's hot image to the argument, which may be | |
658 * null indicating that no hot image should be displayed. | |
659 * <p> | |
660 * The hot image is displayed when the mouse enters the receiver. | |
661 * </p> | |
662 * | |
663 * @param image the hot image to display on the receiver (may be null) | |
664 * | |
665 * @exception IllegalArgumentException <ul> | |
666 * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li> | |
667 * </ul> | |
668 * @exception SWTException <ul> | |
669 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
670 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
671 * </ul> | |
672 */ | |
673 public void setHotImage (Image image) { | |
674 checkWidget(); | |
675 if ((style & SWT.SEPARATOR) !is 0) return; | |
676 if (image !is null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); | |
677 hotImage = image; | |
678 updateImages (getEnabled () && parent.getEnabled ()); | |
679 } | |
680 | |
681 override public void setImage (Image image) { | |
682 checkWidget(); | |
683 if ((style & SWT.SEPARATOR) !is 0) return; | |
684 if (image !is null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); | |
685 super.setImage (image); | |
686 updateImages (getEnabled () && parent.getEnabled ()); | |
687 } | |
688 | |
689 bool setRadioSelection (bool value) { | |
690 if ((style & SWT.RADIO) is 0) return false; | |
691 if (getSelection () !is value) { | |
692 setSelection (value); | |
693 postEvent (SWT.Selection); | |
694 } | |
695 return true; | |
696 } | |
697 | |
698 /** | |
699 * Sets the selection state of the receiver. | |
700 * <p> | |
701 * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>, | |
702 * it is selected when it is checked (which some platforms draw as a | |
703 * pushed in button). | |
704 * </p> | |
705 * | |
706 * @param selected the new selection state | |
707 * | |
708 * @exception SWTException <ul> | |
709 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
710 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
711 * </ul> | |
712 */ | |
713 public void setSelection (bool selected) { | |
714 checkWidget(); | |
715 if ((style & (SWT.CHECK | SWT.RADIO)) is 0) return; | |
716 auto hwnd = parent.handle; | |
717 int fsState = OS.SendMessage (hwnd, OS.TB_GETSTATE, id, 0); | |
718 /* | |
719 * Feature in Windows. When TB_SETSTATE is used to set the | |
720 * state of a tool item, the item redraws even when the state | |
721 * has not changed. The fix is to detect this case and avoid | |
722 * setting the state. | |
723 */ | |
724 if (((fsState & OS.TBSTATE_CHECKED) !is 0) is selected) return; | |
725 if (selected) { | |
726 fsState |= OS.TBSTATE_CHECKED; | |
727 } else { | |
728 fsState &= ~OS.TBSTATE_CHECKED; | |
729 } | |
730 OS.SendMessage (hwnd, OS.TB_SETSTATE, id, fsState); | |
731 | |
732 /* | |
733 * Bug in Windows. When a tool item with the style | |
734 * BTNS_CHECK or BTNS_CHECKGROUP is selected and then | |
735 * disabled, the item does not draw using the disabled | |
736 * image. The fix is to use the disabled image in all | |
737 * image lists for the item. | |
738 * | |
739 * NOTE: This means that the image list must be updated | |
740 * when the selection changes in a disabled tool item. | |
741 */ | |
742 if ((style & (SWT.CHECK | SWT.RADIO)) !is 0) { | |
743 if (!getEnabled () || !parent.getEnabled ()) { | |
744 updateImages (false); | |
745 } | |
746 } | |
747 } | |
748 | |
749 /** | |
750 * Sets the receiver's text. The string may include | |
751 * the mnemonic character. | |
752 * </p> | |
753 * <p> | |
754 * Mnemonics are indicated by an '&' that causes the next | |
755 * character to be the mnemonic. When the user presses a | |
756 * key sequence that matches the mnemonic, a selection | |
757 * event occurs. On most platforms, the mnemonic appears | |
758 * underlined but may be emphasised in a platform specific | |
759 * manner. The mnemonic indicator character '&' can be | |
760 * escaped by doubling it in the string, causing a single | |
761 * '&' to be displayed. | |
762 * </p> | |
763 * | |
764 * @param string the new text | |
765 * | |
766 * @exception SWTException <ul> | |
767 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
768 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
769 * </ul> | |
770 */ | |
771 override public void setText (String string) { | |
772 checkWidget(); | |
773 // SWT extension: allow null string | |
774 //if (string is null) error (SWT.ERROR_NULL_ARGUMENT); | |
775 if ((style & SWT.SEPARATOR) !is 0) return; | |
776 if (string.equals(text)) return; | |
777 super.setText (string); | |
778 auto hwnd = parent.handle; | |
779 TBBUTTONINFO info; | |
780 info.cbSize = TBBUTTONINFO.sizeof; | |
781 info.dwMask = OS.TBIF_TEXT | OS.TBIF_STYLE; | |
782 info.fsStyle = cast(byte) (widgetStyle () | OS.BTNS_AUTOSIZE); | |
783 auto hHeap = OS.GetProcessHeap (); | |
784 TCHAR* pszText; | |
785 if (string.length !is 0) { | |
786 info.fsStyle |= OS.BTNS_SHOWTEXT; | |
787 TCHAR[] buffer = StrToTCHARs (parent.getCodePage (), string, true ); | |
788 int byteCount = buffer.length * TCHAR.sizeof; | |
789 pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); | |
790 OS.MoveMemory (pszText, buffer.ptr, byteCount); | |
791 info.pszText = pszText; | |
792 } | |
793 OS.SendMessage (hwnd, OS.TB_SETBUTTONINFO, id, &info); | |
794 if (pszText !is null) OS.HeapFree (hHeap, 0, pszText); | |
795 | |
796 /* | |
797 * Bug in Windows. For some reason, when the font is set | |
798 * before any tool item has text, the tool items resize to | |
799 * a very small size. Also, a tool item will only show text | |
800 * when text has already been set on one item and then a new | |
801 * item is created. The fix is to use WM_SETFONT to force | |
802 * the tool bar to redraw and layout. | |
803 */ | |
804 parent.setDropDownItems (false); | |
805 int /*long*/ hFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0); | |
806 OS.SendMessage (hwnd, OS.WM_SETFONT, hFont, 0); | |
807 parent.setDropDownItems (true); | |
808 parent.layoutItems (); | |
809 } | |
810 | |
811 /** | |
812 * Sets the receiver's tool tip text to the argument, which | |
813 * may be null indicating that no tool tip text should be shown. | |
814 * | |
815 * @param string the new tool tip text (or null) | |
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 setToolTipText (String string) { | |
823 checkWidget(); | |
824 toolTipText = string; | |
825 } | |
826 | |
827 /** | |
828 * Sets the width of the receiver, for <code>SEPARATOR</code> ToolItems. | |
829 * | |
830 * @param width the new width | |
831 * | |
832 * @exception SWTException <ul> | |
833 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
834 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
835 * </ul> | |
836 */ | |
837 public void setWidth (int width) { | |
838 checkWidget(); | |
839 if ((style & SWT.SEPARATOR) is 0) return; | |
840 if (width < 0) return; | |
841 auto hwnd = parent.handle; | |
842 TBBUTTONINFO info; | |
843 info.cbSize = TBBUTTONINFO.sizeof; | |
844 info.dwMask = OS.TBIF_SIZE; | |
845 info.cx = cast(short) width; | |
846 OS.SendMessage (hwnd, OS.TB_SETBUTTONINFO, id, &info); | |
847 parent.layoutItems (); | |
848 } | |
849 | |
850 void updateImages (bool enabled) { | |
851 if ((style & SWT.SEPARATOR) !is 0) return; | |
852 auto hwnd = parent.handle; | |
853 TBBUTTONINFO info; | |
854 info.cbSize = TBBUTTONINFO.sizeof; | |
855 info.dwMask = OS.TBIF_IMAGE; | |
856 OS.SendMessage (hwnd, OS.TB_GETBUTTONINFO, id, &info); | |
857 if (info.iImage is OS.I_IMAGENONE && image is null) return; | |
858 ImageList imageList = parent.getImageList (); | |
859 ImageList hotImageList = parent.getHotImageList (); | |
860 ImageList disabledImageList = parent.getDisabledImageList(); | |
861 if (info.iImage is OS.I_IMAGENONE) { | |
862 Rectangle bounds = image.getBounds (); | |
863 int listStyle = parent.style & SWT.RIGHT_TO_LEFT; | |
864 if (imageList is null) { | |
865 imageList = display.getImageListToolBar (listStyle, bounds.width, bounds.height); | |
866 } | |
867 if (disabledImageList is null) { | |
868 disabledImageList = display.getImageListToolBarDisabled (listStyle, bounds.width, bounds.height); | |
869 } | |
870 if (hotImageList is null) { | |
871 hotImageList = display.getImageListToolBarHot (listStyle, bounds.width, bounds.height); | |
872 } | |
873 Image disabled = disabledImage; | |
874 if (disabledImage is null) { | |
875 if (disabledImage2 !is null) disabledImage2.dispose (); | |
876 disabledImage2 = null; | |
877 disabled = image; | |
878 if (!enabled) { | |
879 disabled = disabledImage2 = new Image (display, image, SWT.IMAGE_DISABLE); | |
880 } | |
881 } | |
882 /* | |
883 * Bug in Windows. When a tool item with the style | |
884 * BTNS_CHECK or BTNS_CHECKGROUP is selected and then | |
885 * disabled, the item does not draw using the disabled | |
886 * image. The fix is to assign the disabled image in | |
887 * all image lists. | |
888 */ | |
889 Image image2 = image, hot = hotImage; | |
890 if ((style & (SWT.CHECK | SWT.RADIO)) !is 0) { | |
891 if (!enabled) image2 = hot = disabled; | |
892 } | |
893 info.iImage = imageList.add (image2); | |
894 disabledImageList.add (disabled); | |
895 hotImageList.add (hot !is null ? hot : image2); | |
896 parent.setImageList (imageList); | |
897 parent.setDisabledImageList (disabledImageList); | |
898 parent.setHotImageList (hotImageList); | |
899 } else { | |
900 Image disabled = null; | |
901 if (disabledImageList !is null) { | |
902 if (image !is null) { | |
903 if (disabledImage2 !is null) disabledImage2.dispose (); | |
904 disabledImage2 = null; | |
905 disabled = disabledImage; | |
906 if (disabledImage is null) { | |
907 disabled = image; | |
908 if (!enabled) { | |
909 disabled = disabledImage2 = new Image (display, image, SWT.IMAGE_DISABLE); | |
910 } | |
911 } | |
912 } | |
913 disabledImageList.put (info.iImage, disabled); | |
914 } | |
915 /* | |
916 * Bug in Windows. When a tool item with the style | |
917 * BTNS_CHECK or BTNS_CHECKGROUP is selected and then | |
918 * disabled, the item does not draw using the disabled | |
919 * image. The fix is to use the disabled image in all | |
920 * image lists. | |
921 */ | |
922 Image image2 = image, hot = hotImage; | |
923 if ((style & (SWT.CHECK | SWT.RADIO)) !is 0) { | |
924 if (!enabled) image2 = hot = disabled; | |
925 } | |
926 if (imageList !is null) imageList.put (info.iImage, image2); | |
927 if (hotImageList !is null) { | |
928 hotImageList.put (info.iImage, hot !is null ? hot : image2); | |
929 } | |
930 if (image is null) info.iImage = OS.I_IMAGENONE; | |
931 } | |
932 | |
933 /* | |
934 * Bug in Windows. If the width of an item has already been | |
935 * calculated, the tool bar control will not recalculate it to | |
936 * include the space for the image. The fix is to set the width | |
937 * to zero, forcing the control recalculate the width for the item. | |
938 */ | |
939 info.dwMask |= OS.TBIF_SIZE; | |
940 info.cx = 0; | |
941 OS.SendMessage (hwnd, OS.TB_SETBUTTONINFO, id, &info); | |
942 | |
943 parent.layoutItems (); | |
944 } | |
945 | |
946 int widgetStyle () { | |
947 if ((style & SWT.DROP_DOWN) !is 0) return OS.BTNS_DROPDOWN; | |
948 if ((style & SWT.PUSH) !is 0) return OS.BTNS_BUTTON; | |
949 if ((style & SWT.CHECK) !is 0) return OS.BTNS_CHECK; | |
950 /* | |
951 * This code is intentionally commented. In order to | |
952 * consistently support radio tool items across platforms, | |
953 * the platform radio behavior is not used. | |
954 */ | |
955 // if ((style & SWT.RADIO) !is 0) return OS.BTNS_CHECKGROUP; | |
956 if ((style & SWT.RADIO) !is 0) return OS.BTNS_CHECK; | |
957 if ((style & SWT.SEPARATOR) !is 0) return OS.BTNS_SEP; | |
958 return OS.BTNS_BUTTON; | |
959 } | |
960 | |
961 LRESULT wmCommandChild (int /*long*/ wParam, int /*long*/ lParam) { | |
962 if ((style & SWT.RADIO) !is 0) { | |
963 if ((parent.getStyle () & SWT.NO_RADIO_GROUP) is 0) { | |
964 selectRadio (); | |
965 } | |
966 } | |
967 postEvent (SWT.Selection); | |
968 return null; | |
969 } | |
970 | |
971 } | |
972 |