comparison dwt/widgets/MenuItem.d @ 0:380af2bdd8e5

Upload of whole dwt tree
author Jacob Carlborg <doob@me.com> <jacob.carlborg@gmail.com>
date Sat, 09 Aug 2008 17:00:02 +0200
parents
children 649b8e223d5a
comparison
equal deleted inserted replaced
-1:000000000000 0:380af2bdd8e5
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 module dwt.widgets.MenuItem;
12
13 import dwt.dwthelper.utils;
14
15
16 import dwt.DWT;
17 import dwt.DWTException;
18 import dwt.events.ArmListener;
19 import dwt.events.HelpListener;
20 import dwt.events.SelectionEvent;
21 import dwt.events.SelectionListener;
22 import dwt.graphics.Image;
23 import dwt.internal.cocoa.NSMenu;
24 import dwt.internal.cocoa.NSMenuItem;
25 import dwt.internal.cocoa.NSString;
26 import dwt.internal.cocoa.OS;
27 import dwt.internal.cocoa.SWTMenu;
28
29 /**
30 * Instances of this class represent a selectable user interface object
31 * that issues notification when pressed and released.
32 * <dl>
33 * <dt><b>Styles:</b></dt>
34 * <dd>CHECK, CASCADE, PUSH, RADIO, SEPARATOR</dd>
35 * <dt><b>Events:</b></dt>
36 * <dd>Arm, Help, Selection</dd>
37 * </dl>
38 * <p>
39 * Note: Only one of the styles CHECK, CASCADE, PUSH, RADIO and SEPARATOR
40 * may be specified.
41 * </p><p>
42 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
43 * </p>
44 */
45 public class MenuItem extends Item {
46 NSMenuItem nsItem;
47 Menu parent, menu;
48 int accelerator;
49 // int x, y, width, height;
50
51 /**
52 * Constructs a new instance of this class given its parent
53 * (which must be a <code>Menu</code>) and a style value
54 * describing its behavior and appearance. The item is added
55 * to the end of the items maintained by its parent.
56 * <p>
57 * The style value is either one of the style constants defined in
58 * class <code>DWT</code> which is applicable to instances of this
59 * class, or must be built by <em>bitwise OR</em>'ing together
60 * (that is, using the <code>int</code> "|" operator) two or more
61 * of those <code>DWT</code> style constants. The class description
62 * lists the style constants that are applicable to the class.
63 * Style bits are also inherited from superclasses.
64 * </p>
65 *
66 * @param parent a menu control which will be the parent of the new instance (cannot be null)
67 * @param style the style of control to construct
68 *
69 * @exception IllegalArgumentException <ul>
70 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
71 * </ul>
72 * @exception DWTException <ul>
73 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
74 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
75 * </ul>
76 *
77 * @see DWT#CHECK
78 * @see DWT#CASCADE
79 * @see DWT#PUSH
80 * @see DWT#RADIO
81 * @see DWT#SEPARATOR
82 * @see Widget#checkSubclass
83 * @see Widget#getStyle
84 */
85 public MenuItem (Menu parent, int style) {
86 super (parent, checkStyle (style));
87 this.parent = parent;
88 parent.createItem (this, parent.getItemCount ());
89 }
90
91 /**
92 * Constructs a new instance of this class given its parent
93 * (which must be a <code>Menu</code>), a style value
94 * describing its behavior and appearance, and the index
95 * at which to place it in the items maintained by its parent.
96 * <p>
97 * The style value is either one of the style constants defined in
98 * class <code>DWT</code> which is applicable to instances of this
99 * class, or must be built by <em>bitwise OR</em>'ing together
100 * (that is, using the <code>int</code> "|" operator) two or more
101 * of those <code>DWT</code> style constants. The class description
102 * lists the style constants that are applicable to the class.
103 * Style bits are also inherited from superclasses.
104 * </p>
105 *
106 * @param parent a menu control which will be the parent of the new instance (cannot be null)
107 * @param style the style of control to construct
108 * @param index the zero-relative index to store the receiver in its parent
109 *
110 * @exception IllegalArgumentException <ul>
111 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
112 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
113 * </ul>
114 * @exception DWTException <ul>
115 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
116 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
117 * </ul>
118 *
119 * @see DWT#CHECK
120 * @see DWT#CASCADE
121 * @see DWT#PUSH
122 * @see DWT#RADIO
123 * @see DWT#SEPARATOR
124 * @see Widget#checkSubclass
125 * @see Widget#getStyle
126 */
127 public MenuItem (Menu parent, int style, int index) {
128 super (parent, checkStyle (style));
129 this.parent = parent;
130 parent.createItem (this, index);
131 }
132
133 /**
134 * Adds the listener to the collection of listeners who will
135 * be notified when the arm events are generated for the control, by sending
136 * it one of the messages defined in the <code>ArmListener</code>
137 * interface.
138 *
139 * @param listener the listener which should be notified
140 *
141 * @exception IllegalArgumentException <ul>
142 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
143 * </ul>
144 * @exception DWTException <ul>
145 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
146 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
147 * </ul>
148 *
149 * @see ArmListener
150 * @see #removeArmListener
151 */
152 public void addArmListener (ArmListener listener) {
153 checkWidget ();
154 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
155 TypedListener typedListener = new TypedListener (listener);
156 addListener (DWT.Arm, typedListener);
157 }
158
159 /**
160 * Adds the listener to the collection of listeners who will
161 * be notified when the help events are generated for the control, by sending
162 * it one of the messages defined in the <code>HelpListener</code>
163 * interface.
164 *
165 * @param listener the listener which should be notified
166 *
167 * @exception IllegalArgumentException <ul>
168 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
169 * </ul>
170 * @exception DWTException <ul>
171 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
172 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
173 * </ul>
174 *
175 * @see HelpListener
176 * @see #removeHelpListener
177 */
178 public void addHelpListener (HelpListener listener) {
179 checkWidget ();
180 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
181 TypedListener typedListener = new TypedListener (listener);
182 addListener (DWT.Help, typedListener);
183 }
184
185 /**
186 * Adds the listener to the collection of listeners who will
187 * be notified when the menu item is selected by the user, by sending
188 * it one of the messages defined in the <code>SelectionListener</code>
189 * interface.
190 * <p>
191 * When <code>widgetSelected</code> is called, the stateMask field of the event object is valid.
192 * <code>widgetDefaultSelected</code> is not called.
193 * </p>
194 *
195 * @param listener the listener which should be notified when the menu item is selected by the user
196 *
197 * @exception IllegalArgumentException <ul>
198 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
199 * </ul>
200 * @exception DWTException <ul>
201 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
202 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
203 * </ul>
204 *
205 * @see SelectionListener
206 * @see #removeSelectionListener
207 * @see SelectionEvent
208 */
209 public void addSelectionListener (SelectionListener listener) {
210 checkWidget ();
211 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
212 TypedListener typedListener = new TypedListener(listener);
213 addListener (DWT.Selection,typedListener);
214 addListener (DWT.DefaultSelection,typedListener);
215 }
216
217 protected void checkSubclass () {
218 if (!isValidSubclass ()) error (DWT.ERROR_INVALID_SUBCLASS);
219 }
220
221 static int checkStyle (int style) {
222 return checkBits (style, DWT.PUSH, DWT.CHECK, DWT.RADIO, DWT.SEPARATOR, DWT.CASCADE, 0);
223 }
224
225 NSMenu createEmptyMenu () {
226 if ((parent.style & DWT.BAR) !is 0) {
227 return (NSMenu) new SWTMenu ().alloc ().init ();
228 }
229 return null;
230 }
231
232 void destroyWidget () {
233 parent.destroyItem (this);
234 releaseHandle ();
235 }
236
237 /**
238 * Returns the widget accelerator. An accelerator is the bit-wise
239 * OR of zero or more modifier masks and a key. Examples:
240 * <code>DWT.CONTROL | DWT.SHIFT | 'T', DWT.ALT | DWT.F2</code>.
241 * The default value is zero, indicating that the menu item does
242 * not have an accelerator.
243 *
244 * @return the accelerator or 0
245 *
246 * </ul>
247 * @exception DWTException <ul>
248 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
249 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
250 * </ul>
251 */
252 public int getAccelerator () {
253 checkWidget ();
254 return accelerator;
255 }
256
257 /**
258 * Returns <code>true</code> if the receiver is enabled, and
259 * <code>false</code> otherwise. A disabled menu item is typically
260 * not selectable from the user interface and draws with an
261 * inactive or "grayed" look.
262 *
263 * @return the receiver's enabled state
264 *
265 * @exception DWTException <ul>
266 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
267 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
268 * </ul>
269 *
270 * @see #isEnabled
271 */
272 public bool getEnabled () {
273 checkWidget();
274 return (state & DISABLED) is 0;
275 }
276
277 /**
278 * Returns the receiver's cascade menu if it has one or null
279 * if it does not. Only <code>CASCADE</code> menu items can have
280 * a pull down menu. The sequence of key strokes, button presses
281 * and/or button releases that are used to request a pull down
282 * menu is platform specific.
283 *
284 * @return the receiver's menu
285 *
286 * @exception DWTException <ul>
287 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
288 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
289 * </ul>
290 */
291 public Menu getMenu () {
292 checkWidget ();
293 return menu;
294 }
295
296 String getNameText () {
297 if ((style & DWT.SEPARATOR) !is 0) return "|";
298 return super.getNameText ();
299 }
300
301 /**
302 * Returns the receiver's parent, which must be a <code>Menu</code>.
303 *
304 * @return the receiver's parent
305 *
306 * @exception DWTException <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 Menu getParent () {
312 checkWidget ();
313 return parent;
314 }
315
316 /**
317 * Returns <code>true</code> if the receiver is selected,
318 * and false otherwise.
319 * <p>
320 * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
321 * it is selected when it is checked.
322 *
323 * @return the selection state
324 *
325 * @exception DWTException <ul>
326 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
327 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
328 * </ul>
329 */
330 public bool getSelection () {
331 checkWidget ();
332 if ((style & (DWT.CHECK | DWT.RADIO)) is 0) return false;
333 return ((NSMenuItem)nsItem).state() is OS.NSOnState;
334 }
335
336 //int kEventProcessCommand (int nextHandler, int theEvent, int userData) {
337 // //TEMPORARY CODE
338 // if (!isEnabled ()) return OS.noErr;
339 //
340 // if ((style & DWT.CHECK) !is 0) {
341 // setSelection (!getSelection ());
342 // } else {
343 // if ((style & DWT.RADIO) !is 0) {
344 // if ((parent.getStyle () & DWT.NO_RADIO_GROUP) !is 0) {
345 // setSelection (!getSelection ());
346 // } else {
347 // selectRadio ();
348 // }
349 // }
350 // }
351 // int [] modifiers = new int [1];
352 // OS.GetEventParameter (theEvent, OS.kEventParamKeyModifiers, OS.typeUInt32, null, 4, null, modifiers);
353 // Event event = new Event ();
354 // setInputState (event, (short) 0, OS.GetCurrentEventButtonState (), modifiers [0]);
355 // postEvent (DWT.Selection, event);
356 // return OS.noErr;
357 //}
358
359 /**
360 * Returns <code>true</code> if the receiver is enabled and all
361 * of the receiver's ancestors are enabled, and <code>false</code>
362 * otherwise. A disabled menu item is typically not selectable from the
363 * user interface and draws with an inactive or "grayed" look.
364 *
365 * @return the receiver's enabled state
366 *
367 * @exception DWTException <ul>
368 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
369 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
370 * </ul>
371 *
372 * @see #getEnabled
373 */
374 public bool isEnabled () {
375 return getEnabled () && parent.isEnabled ();
376 }
377
378 //int keyGlyph (int key) {
379 // switch (key) {
380 // case DWT.BS: return OS.kMenuDeleteLeftGlyph;
381 // case DWT.CR: return OS.kMenuReturnGlyph;
382 // case DWT.DEL: return OS.kMenuDeleteRightGlyph;
383 // case DWT.ESC: return OS.kMenuEscapeGlyph;
384 // case DWT.LF: return OS.kMenuReturnGlyph;
385 // case DWT.TAB: return OS.kMenuTabRightGlyph;
386 // case ' ': return OS.kMenuBlankGlyph;
387 //// case ' ': return OS.kMenuSpaceGlyph;
388 // case DWT.ALT: return OS.kMenuOptionGlyph;
389 // case DWT.SHIFT: return OS.kMenuShiftGlyph;
390 // case DWT.CONTROL: return OS.kMenuControlISOGlyph;
391 // case DWT.COMMAND: return OS.kMenuCommandGlyph;
392 // case DWT.ARROW_UP: return OS.kMenuUpArrowGlyph;
393 // case DWT.ARROW_DOWN: return OS.kMenuDownArrowGlyph;
394 // case DWT.ARROW_LEFT: return OS.kMenuLeftArrowGlyph;
395 // case DWT.ARROW_RIGHT: return OS.kMenuRightArrowGlyph;
396 // case DWT.PAGE_UP: return OS.kMenuPageUpGlyph;
397 // case DWT.PAGE_DOWN: return OS.kMenuPageDownGlyph;
398 // case DWT.F1: return OS.kMenuF1Glyph;
399 // case DWT.F2: return OS.kMenuF2Glyph;
400 // case DWT.F3: return OS.kMenuF3Glyph;
401 // case DWT.F4: return OS.kMenuF4Glyph;
402 // case DWT.F5: return OS.kMenuF5Glyph;
403 // case DWT.F6: return OS.kMenuF6Glyph;
404 // case DWT.F7: return OS.kMenuF7Glyph;
405 // case DWT.F8: return OS.kMenuF8Glyph;
406 // case DWT.F9: return OS.kMenuF9Glyph;
407 // case DWT.F10: return OS.kMenuF10Glyph;
408 // case DWT.F11: return OS.kMenuF11Glyph;
409 // case DWT.F12: return OS.kMenuF12Glyph;
410 // }
411 // return OS.kMenuNullGlyph;
412 //}
413
414 void releaseHandle () {
415 super.releaseHandle ();
416 if (nsItem !is null) nsItem.release();
417 nsItem = null;
418 parent = null;
419 }
420
421 void releaseChildren (bool destroy) {
422 if (menu !is null) {
423 menu.release (false);
424 menu = null;
425 }
426 super.releaseChildren (destroy);
427 }
428
429 void releaseWidget () {
430 super.releaseWidget ();
431 accelerator = 0;
432 if (this is parent.defaultItem) parent.defaultItem = null;
433 }
434
435 /**
436 * Removes the listener from the collection of listeners who will
437 * be notified when the arm events are generated for the control.
438 *
439 * @param listener the listener which should no longer be notified
440 *
441 * @exception IllegalArgumentException <ul>
442 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
443 * </ul>
444 * @exception DWTException <ul>
445 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
446 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
447 * </ul>
448 *
449 * @see ArmListener
450 * @see #addArmListener
451 */
452 public void removeArmListener (ArmListener listener) {
453 checkWidget ();
454 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
455 if (eventTable is null) return;
456 eventTable.unhook (DWT.Arm, listener);
457 }
458
459 /**
460 * Removes the listener from the collection of listeners who will
461 * be notified when the help events are generated for the control.
462 *
463 * @param listener the listener which should no longer be notified
464 *
465 * @exception IllegalArgumentException <ul>
466 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
467 * </ul>
468 * @exception DWTException <ul>
469 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
470 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
471 * </ul>
472 *
473 * @see HelpListener
474 * @see #addHelpListener
475 */
476 public void removeHelpListener (HelpListener listener) {
477 checkWidget ();
478 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
479 if (eventTable is null) return;
480 eventTable.unhook (DWT.Help, listener);
481 }
482
483 /**
484 * Removes the listener from the collection of listeners who will
485 * be notified when the control is selected by the user.
486 *
487 * @param listener the listener which should no longer be notified
488 *
489 * @exception IllegalArgumentException <ul>
490 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
491 * </ul>
492 * @exception DWTException <ul>
493 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
494 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
495 * </ul>
496 *
497 * @see SelectionListener
498 * @see #addSelectionListener
499 */
500 public void removeSelectionListener (SelectionListener listener) {
501 checkWidget ();
502 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
503 if (eventTable is null) return;
504 eventTable.unhook (DWT.Selection, listener);
505 eventTable.unhook (DWT.DefaultSelection,listener);
506 }
507
508 void selectRadio () {
509 int index = 0;
510 MenuItem [] items = parent.getItems ();
511 while (index < items.length && items [index] !is this) index++;
512 int i = index - 1;
513 while (i >= 0 && items [i].setRadioSelection (false)) --i;
514 int j = index + 1;
515 while (j < items.length && items [j].setRadioSelection (false)) j++;
516 setSelection (true);
517 }
518
519 void sendSelection () {
520 if ((style & DWT.CHECK) !is 0) {
521 setSelection (!getSelection ());
522 } else {
523 if ((style & DWT.RADIO) !is 0) {
524 if ((parent.getStyle () & DWT.NO_RADIO_GROUP) !is 0) {
525 setSelection (!getSelection ());
526 } else {
527 selectRadio ();
528 }
529 }
530 }
531 Event event = new Event ();
532 //TODO state mask
533 // setInputState (event, (short) 0, OS.GetCurrentEventButtonState (), modifiers [0]);
534 postEvent (DWT.Selection, event);
535 }
536
537 /**
538 * Sets the widget accelerator. An accelerator is the bit-wise
539 * OR of zero or more modifier masks and a key. Examples:
540 * <code>DWT.MOD1 | DWT.MOD2 | 'T', DWT.MOD3 | DWT.F2</code>.
541 * <code>DWT.CONTROL | DWT.SHIFT | 'T', DWT.ALT | DWT.F2</code>.
542 * The default value is zero, indicating that the menu item does
543 * not have an accelerator.
544 *
545 * @param accelerator an integer that is the bit-wise OR of masks and a key
546 *
547 * </ul>
548 * @exception DWTException <ul>
549 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
550 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
551 * </ul>
552 */
553 public void setAccelerator (int accelerator) {
554 checkWidget ();
555 this.accelerator = accelerator;
556 int key = accelerator & DWT.KEY_MASK;
557 int virtualKey = Display.untranslateKey (key);
558 NSString string = null;
559 if (virtualKey !is 0) {
560 string = NSString.stringWith ((char)virtualKey + "");
561 } else {
562 string = NSString.stringWith ((char)key + "").lowercaseString();
563 }
564 nsItem.setKeyEquivalent (string);
565 int mask = 0;
566 if ((accelerator & DWT.SHIFT) !is 0) mask |= OS.NSShiftKeyMask;
567 if ((accelerator & DWT.CONTROL) !is 0) mask |= OS.NSControlKeyMask;
568 // if ((accelerator & DWT.COMMAND) !is 0) mask &= ~OS.kMenuNoCommandModifier;
569 if ((accelerator & DWT.COMMAND) !is 0) mask |= OS.NSCommandKeyMask;
570 if ((accelerator & DWT.ALT) !is 0) mask |= OS.NSAlternateKeyMask;
571 nsItem.setKeyEquivalentModifierMask (mask);
572 if ((this.accelerator is 0 && accelerator !is 0) || (this.accelerator !is 0 && accelerator is 0)) {
573 updateText ();
574 }
575 }
576
577 /**
578 * Enables the receiver if the argument is <code>true</code>,
579 * and disables it otherwise. A disabled menu item is typically
580 * not selectable from the user interface and draws with an
581 * inactive or "grayed" look.
582 *
583 * @param enabled the new enabled state
584 *
585 * @exception DWTException <ul>
586 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
587 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
588 * </ul>
589 */
590 public void setEnabled (bool enabled) {
591 checkWidget ();
592 ((NSMenuItem)nsItem).setEnabled(enabled);
593 }
594
595 /**
596 * Sets the image the receiver will display to the argument.
597 * <p>
598 * Note: This operation is a hint and is not supported on
599 * platforms that do not have this concept (for example, Windows NT).
600 * </p>
601 *
602 * @param image the image to display
603 *
604 * @exception DWTException <ul>
605 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
606 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
607 * </ul>
608 */
609 public void setImage (Image image) {
610 checkWidget ();
611 if ((style & DWT.SEPARATOR) !is 0) return;
612 super.setImage (image);
613 ((NSMenuItem)nsItem).setImage(image !is null? image.handle : null);
614 }
615
616 /**
617 * Sets the receiver's pull down menu to the argument.
618 * Only <code>CASCADE</code> menu items can have a
619 * pull down menu. The sequence of key strokes, button presses
620 * and/or button releases that are used to request a pull down
621 * menu is platform specific.
622 * <p>
623 * Note: Disposing of a menu item that has a pull down menu
624 * will dispose of the menu. To avoid this behavior, set the
625 * menu to null before the menu item is disposed.
626 * </p>
627 *
628 * @param menu the new pull down menu
629 *
630 * @exception IllegalArgumentException <ul>
631 * <li>ERROR_MENU_NOT_DROP_DOWN - if the menu is not a drop down menu</li>
632 * <li>ERROR_MENUITEM_NOT_CASCADE - if the menu item is not a <code>CASCADE</code></li>
633 * <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</li>
634 * <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</li>
635 * </ul>
636 * @exception DWTException <ul>
637 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
638 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
639 * </ul>
640 */
641 public void setMenu (Menu menu) {
642 checkWidget ();
643
644 /* Check to make sure the new menu is valid */
645 if ((style & DWT.CASCADE) is 0) {
646 error (DWT.ERROR_MENUITEM_NOT_CASCADE);
647 }
648 if (menu !is null) {
649 if (menu.isDisposed()) error(DWT.ERROR_INVALID_ARGUMENT);
650 if ((menu.style & DWT.DROP_DOWN) is 0) {
651 error (DWT.ERROR_MENU_NOT_DROP_DOWN);
652 }
653 if (menu.parent !is parent.parent) {
654 error (DWT.ERROR_INVALID_PARENT);
655 }
656 }
657 /* Assign the new menu */
658 Menu oldMenu = this.menu;
659 if (oldMenu is menu) return;
660 if (oldMenu !is null) oldMenu.cascade = null;
661 this.menu = menu;
662
663 /* Update the menu in the OS */
664 NSMenu menuHandle;
665 if (menu is null) {
666 menuHandle = createEmptyMenu ();
667 } else {
668 menu.cascade = this;
669 menuHandle = menu.nsMenu;
670 }
671 nsItem.setSubmenu (menuHandle);
672
673 /* Update menu title with parent item title */
674 updateText ();
675 }
676
677 bool setRadioSelection (bool value) {
678 if ((style & DWT.RADIO) is 0) return false;
679 if (getSelection () !is value) {
680 setSelection (value);
681 postEvent (DWT.Selection);
682 }
683 return true;
684 }
685
686 /**
687 * Sets the selection state of the receiver.
688 * <p>
689 * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
690 * it is selected when it is checked.
691 *
692 * @param selected the new selection state
693 *
694 * @exception DWTException <ul>
695 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
696 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
697 * </ul>
698 */
699 public void setSelection (bool selected) {
700 checkWidget ();
701 if ((style & (DWT.CHECK | DWT.RADIO)) is 0) return;
702 ((NSMenuItem)nsItem).setState(selected ? OS.NSOnState : OS.NSOffState);
703 }
704
705 /**
706 * Sets the receiver's text. The string may include
707 * the mnemonic character and accelerator text.
708 * <p>
709 * Mnemonics are indicated by an '&amp;' that causes the next
710 * character to be the mnemonic. When the user presses a
711 * key sequence that matches the mnemonic, a selection
712 * event occurs. On most platforms, the mnemonic appears
713 * underlined but may be emphasised in a platform specific
714 * manner. The mnemonic indicator character '&amp;' can be
715 * escaped by doubling it in the string, causing a single
716 * '&amp;' to be displayed.
717 * </p>
718 * <p>
719 * Accelerator text is indicated by the '\t' character.
720 * On platforms that support accelerator text, the text
721 * that follows the '\t' character is displayed to the user,
722 * typically indicating the key stroke that will cause
723 * the item to become selected. On most platforms, the
724 * accelerator text appears right aligned in the menu.
725 * Setting the accelerator text does not install the
726 * accelerator key sequence. The accelerator key sequence
727 * is installed using #setAccelerator.
728 * </p>
729 *
730 * @param string the new text
731 *
732 * @exception IllegalArgumentException <ul>
733 * <li>ERROR_NULL_ARGUMENT - if the text is null</li>
734 * </ul>
735 * @exception DWTException <ul>
736 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
737 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
738 * </ul>
739 *
740 * @see #setAccelerator
741 */
742 public void setText (String string) {
743 checkWidget ();
744 if (string is null) error (DWT.ERROR_NULL_ARGUMENT);
745 if ((style & DWT.SEPARATOR) !is 0) return;
746 if (text.equals (string)) return;
747 super.setText (string);
748 updateText ();
749 }
750
751 void updateText() {
752 char [] buffer = new char [text.length ()];
753 text.getChars (0, buffer.length, buffer, 0);
754 int i=0, j=0;
755 while (i < buffer.length) {
756 if (buffer [i] is '\t') break;
757 if ((buffer [j++] = buffer [i++]) is '&') {
758 if (i is buffer.length) {continue;}
759 if (buffer [i] is '&') {i++; continue;}
760 j--;
761 }
762 }
763 String text = new String (buffer, 0, j);
764 NSMenu submenu = nsItem.submenu ();
765 NSString label = NSString.stringWith (text);
766 if(submenu !is null && (parent.getStyle () & DWT.BAR) !is 0) {
767 submenu.setTitle (label);
768 } else {
769 nsItem.setTitle (label);
770 }
771 }
772
773 }
774