Mercurial > projects > dwt-mac
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 '&' 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 '&' can be | |
715 * escaped by doubling it in the string, causing a single | |
716 * '&' 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 |