comparison dwt/widgets/Menu.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.Menu;
12
13 import dwt.dwthelper.utils;
14
15
16 import dwt.DWT;
17 import dwt.DWTException;
18 import dwt.events.HelpListener;
19 import dwt.events.MenuListener;
20 import dwt.graphics.Point;
21 import dwt.internal.cocoa.NSEvent;
22 import dwt.internal.cocoa.NSMenu;
23 import dwt.internal.cocoa.NSMenuItem;
24 import dwt.internal.cocoa.NSPoint;
25 import dwt.internal.cocoa.NSString;
26 import dwt.internal.cocoa.NSView;
27 import dwt.internal.cocoa.NSWindow;
28 import dwt.internal.cocoa.OS;
29 import dwt.internal.cocoa.SWTMenu;
30 import dwt.internal.cocoa.SWTMenuItem;
31
32 /**
33 * Instances of this class are user interface objects that contain
34 * menu items.
35 * <dl>
36 * <dt><b>Styles:</b></dt>
37 * <dd>BAR, DROP_DOWN, POP_UP, NO_RADIO_GROUP</dd>
38 * <dd>LEFT_TO_RIGHT, RIGHT_TO_LEFT</dd>
39 * <dt><b>Events:</b></dt>
40 * <dd>Help, Hide, Show </dd>
41 * </dl>
42 * <p>
43 * Note: Only one of BAR, DROP_DOWN and POP_UP may be specified.
44 * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified.
45 * </p><p>
46 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
47 * </p>
48 */
49 public class Menu extends Widget {
50 /**
51 * the handle to the OS resource
52 * (Warning: This field is platform dependent)
53 * <p>
54 * <b>IMPORTANT:</b> This field is <em>not</em> part of the DWT
55 * public API. It is marked public only so that it can be shared
56 * within the packages provided by DWT. It is not available on all
57 * platforms and should never be accessed from application code.
58 * </p>
59 */
60 NSMenu nsMenu;
61 short id;
62 int x, y, itemCount;
63 // int width, height;
64 bool hasLocation, modified, closed;
65 MenuItem [] items;
66 MenuItem cascade, defaultItem, lastTarget;
67 Decorations parent;
68
69 /**
70 * Constructs a new instance of this class given its parent,
71 * and sets the style for the instance so that the instance
72 * will be a popup menu on the given parent's shell.
73 *
74 * @param parent a control which will be the parent of the new instance (cannot be null)
75 *
76 * @exception IllegalArgumentException <ul>
77 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
78 * </ul>
79 * @exception DWTException <ul>
80 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
81 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
82 * </ul>
83 *
84 * @see DWT#POP_UP
85 * @see Widget#checkSubclass
86 * @see Widget#getStyle
87 */
88 public Menu (Control parent) {
89 this (checkNull (parent).menuShell (), DWT.POP_UP);
90 }
91
92 /**
93 * Constructs a new instance of this class given its parent
94 * (which must be a <code>Decorations</code>) and a style value
95 * describing its behavior and appearance.
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 decorations control which will be the parent of the new instance (cannot be null)
107 * @param style the style of menu to construct
108 *
109 * @exception IllegalArgumentException <ul>
110 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
111 * </ul>
112 * @exception DWTException <ul>
113 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
114 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
115 * </ul>
116 *
117 * @see DWT#BAR
118 * @see DWT#DROP_DOWN
119 * @see DWT#POP_UP
120 * @see Widget#checkSubclass
121 * @see Widget#getStyle
122 */
123 public Menu (Decorations parent, int style) {
124 super (parent, checkStyle (style));
125 this.parent = parent;
126 createWidget ();
127 }
128
129 /**
130 * Constructs a new instance of this class given its parent
131 * (which must be a <code>Menu</code>) and sets the style
132 * for the instance so that the instance will be a drop-down
133 * menu on the given parent's parent.
134 *
135 * @param parentMenu a menu which will be the parent of the new instance (cannot be null)
136 *
137 * @exception IllegalArgumentException <ul>
138 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
139 * </ul>
140 * @exception DWTException <ul>
141 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
142 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
143 * </ul>
144 *
145 * @see DWT#DROP_DOWN
146 * @see Widget#checkSubclass
147 * @see Widget#getStyle
148 */
149 public Menu (Menu parentMenu) {
150 this (checkNull (parentMenu).parent, DWT.DROP_DOWN);
151 }
152
153 /**
154 * Constructs a new instance of this class given its parent
155 * (which must be a <code>MenuItem</code>) and sets the style
156 * for the instance so that the instance will be a drop-down
157 * menu on the given parent's parent menu.
158 *
159 * @param parentItem a menu item which will be the parent of the new instance (cannot be null)
160 *
161 * @exception IllegalArgumentException <ul>
162 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
163 * </ul>
164 * @exception DWTException <ul>
165 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
166 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
167 * </ul>
168 *
169 * @see DWT#DROP_DOWN
170 * @see Widget#checkSubclass
171 * @see Widget#getStyle
172 */
173 public Menu (MenuItem parentItem) {
174 this (checkNull (parentItem).parent);
175 }
176
177 static Control checkNull (Control control) {
178 if (control is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
179 return control;
180 }
181
182 static Menu checkNull (Menu menu) {
183 if (menu is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
184 return menu;
185 }
186
187 static MenuItem checkNull (MenuItem item) {
188 if (item is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
189 return item;
190 }
191
192 static int checkStyle (int style) {
193 return checkBits (style, DWT.POP_UP, DWT.BAR, DWT.DROP_DOWN, 0, 0, 0);
194 }
195
196 void _setVisible (bool visible) {
197 if ((style & (DWT.BAR | DWT.DROP_DOWN)) !is 0) return;
198 if (visible) {
199 Shell shell = getShell ();
200 NSWindow window = shell.window;
201 NSPoint location = null;
202 if (hasLocation) {
203 NSView topView = window.contentView();
204 Point shellCoord = display.map(null, shell, new Point(x,y));
205 location = new NSPoint ();
206 location.x = shellCoord.x;
207 location.y = topView.frame().height - shellCoord.y;
208 } else {
209 location = window.mouseLocationOutsideOfEventStream();
210 }
211 NSEvent nsEvent = NSEvent.otherEventWithType(OS.NSApplicationDefined, location, 0, 0.0, window.windowNumber(), window.graphicsContext(), (short)0, 0, 0);
212 NSMenu.static_popUpContextMenu_withEvent_forView_ (nsMenu, nsEvent, shell.view);
213 } else {
214 nsMenu.cancelTracking ();
215 }
216 }
217
218 /**
219 * Adds the listener to the collection of listeners who will
220 * be notified when help events are generated for the control,
221 * by sending it one of the messages defined in the
222 * <code>HelpListener</code> interface.
223 *
224 * @param listener the listener which should be notified
225 *
226 * @exception IllegalArgumentException <ul>
227 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
228 * </ul>
229 * @exception DWTException <ul>
230 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
231 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
232 * </ul>
233 *
234 * @see HelpListener
235 * @see #removeHelpListener
236 */
237 public void addHelpListener (HelpListener listener) {
238 checkWidget ();
239 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
240 TypedListener typedListener = new TypedListener (listener);
241 addListener (DWT.Help, typedListener);
242 }
243
244 /**
245 * Adds the listener to the collection of listeners who will
246 * be notified when menus are hidden or shown, by sending it
247 * one of the messages defined in the <code>MenuListener</code>
248 * interface.
249 *
250 * @param listener the listener which should be notified
251 *
252 * @exception IllegalArgumentException <ul>
253 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
254 * </ul>
255 * @exception DWTException <ul>
256 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
257 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
258 * </ul>
259 *
260 * @see MenuListener
261 * @see #removeMenuListener
262 */
263 public void addMenuListener (MenuListener listener) {
264 checkWidget ();
265 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
266 TypedListener typedListener = new TypedListener (listener);
267 addListener (DWT.Hide,typedListener);
268 addListener (DWT.Show,typedListener);
269 }
270
271 void createHandle () {
272 // display.addMenu (this);
273 SWTMenu widget = (SWTMenu)new SWTMenu().alloc();
274 widget.initWithTitle(NSString.stringWith(""));
275 widget.setAutoenablesItems(false);
276 widget.setTag(jniRef);
277 widget.setDelegate(widget);
278 nsMenu = widget;
279 }
280
281 void createItem (MenuItem item, int index) {
282 checkWidget ();
283 if (!(0 <= index && index <= itemCount)) error (DWT.ERROR_INVALID_RANGE);
284 NSMenuItem nsItem = null;
285 if ((item.style & DWT.SEPARATOR) !is 0) {
286 nsItem = NSMenuItem.separatorItem();
287 nsItem.retain();
288 } else {
289 nsItem = (NSMenuItem)new SWTMenuItem().alloc();
290 nsItem.initWithTitle(NSString.stringWith(""), 0, NSString.stringWith(""));
291 nsItem.setTarget(nsItem);
292 nsItem.setAction(OS.sel_sendSelection);
293 item.createJNIRef();
294 nsItem.setTag(item.jniRef);
295 }
296 item.nsItem = nsItem;
297 nsMenu.insertItem(nsItem, index);
298 if (itemCount is items.length) {
299 MenuItem [] newItems = new MenuItem [items.length + 4];
300 System.arraycopy (items, 0, newItems, 0, items.length);
301 items = newItems;
302 }
303 System.arraycopy (items, index, items, index + 1, itemCount++ - index);
304 items [index] = item;
305
306 NSMenu emptyMenu = item.createEmptyMenu ();
307 if (emptyMenu !is null) {
308 item.nsItem.setSubmenu (emptyMenu);
309 }
310 }
311
312 void createWidget () {
313 checkOrientation (parent);
314 super.createWidget ();
315 items = new MenuItem [4];
316 }
317
318 void destroyItem (MenuItem item) {
319 int index = 0;
320 while (index < itemCount) {
321 if (items [index] is item) break;
322 index++;
323 }
324 if (index is itemCount) return;
325 System.arraycopy (items, index + 1, items, index, --itemCount - index);
326 items [itemCount] = null;
327 if (itemCount is 0) items = new MenuItem [4];
328 nsMenu.removeItem (item.nsItem);
329 }
330
331 void destroyWidget () {
332 NSMenu nsMenu = this.nsMenu;
333 releaseHandle ();
334 if (nsMenu !is null) {
335 nsMenu.release();
336 }
337 }
338
339 void fixMenus (Decorations newParent) {
340 this.parent = newParent;
341 }
342
343 /**
344 * Returns the default menu item or null if none has
345 * been previously set.
346 *
347 * @return the default menu item.
348 *
349 * </ul>
350 * @exception DWTException <ul>
351 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
352 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
353 * </ul>
354 */
355 public MenuItem getDefaultItem () {
356 checkWidget();
357 return defaultItem;
358 }
359
360 /**
361 * Returns <code>true</code> if the receiver is enabled, and
362 * <code>false</code> otherwise. A disabled menu is typically
363 * not selectable from the user interface and draws with an
364 * inactive or "grayed" look.
365 *
366 * @return the receiver's enabled state
367 *
368 * @exception DWTException <ul>
369 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
370 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
371 * </ul>
372 *
373 * @see #isEnabled
374 */
375 public bool getEnabled () {
376 checkWidget();
377 return (state & DISABLED) is 0;
378 }
379
380 /**
381 * Returns the item at the given, zero-relative index in the
382 * receiver. Throws an exception if the index is out of range.
383 *
384 * @param index the index of the item to return
385 * @return the item at the given index
386 *
387 * @exception IllegalArgumentException <ul>
388 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
389 * </ul>
390 * @exception DWTException <ul>
391 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
392 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
393 * </ul>
394 */
395 public MenuItem getItem (int index) {
396 checkWidget ();
397 if (!(0 <= index && index < itemCount)) error (DWT.ERROR_INVALID_RANGE);
398 return items [index];
399 }
400
401 /**
402 * Returns the number of items contained in the receiver.
403 *
404 * @return the number of items
405 *
406 * @exception DWTException <ul>
407 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
408 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
409 * </ul>
410 */
411 public int getItemCount () {
412 checkWidget ();
413 return itemCount;
414 }
415
416 /**
417 * Returns a (possibly empty) array of <code>MenuItem</code>s which
418 * are the items in the receiver.
419 * <p>
420 * Note: This is not the actual structure used by the receiver
421 * to maintain its list of items, so modifying the array will
422 * not affect the receiver.
423 * </p>
424 *
425 * @return the items in the receiver
426 *
427 * @exception DWTException <ul>
428 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
429 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
430 * </ul>
431 */
432 public MenuItem [] getItems () {
433 checkWidget ();
434 MenuItem [] result = new MenuItem [itemCount];
435 int index = 0;
436 if (items !is null) {
437 for (int i = 0; i < itemCount; i++) {
438 MenuItem item = items [i];
439 if (item !is null && !item.isDisposed ()) {
440 result [index++] = item;
441 }
442 }
443 }
444 if (index !is result.length) {
445 MenuItem [] newItems = new MenuItem[index];
446 System.arraycopy(result, 0, newItems, 0, index);
447 result = newItems;
448 }
449 return result;
450 }
451
452 String getNameText () {
453 String result = "";
454 MenuItem [] items = getItems ();
455 int length = items.length;
456 if (length > 0) {
457 for (int i=0; i<length-1; i++) {
458 result = result + items [i].getNameText() + ", ";
459 }
460 result = result + items [length-1].getNameText ();
461 }
462 return result;
463 }
464
465 /**
466 * Returns the receiver's parent, which must be a <code>Decorations</code>.
467 *
468 * @return the receiver's parent
469 *
470 * @exception DWTException <ul>
471 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
472 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
473 * </ul>
474 */
475 public Decorations getParent () {
476 checkWidget ();
477 return parent;
478 }
479
480 /**
481 * Returns the receiver's parent item, which must be a
482 * <code>MenuItem</code> or null when the receiver is a
483 * root.
484 *
485 * @return the receiver's parent item
486 *
487 * @exception DWTException <ul>
488 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
489 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
490 * </ul>
491 */
492 public MenuItem getParentItem () {
493 checkWidget ();
494 return cascade;
495 }
496
497 /**
498 * Returns the receiver's parent item, which must be a
499 * <code>Menu</code> or null when the receiver is a
500 * root.
501 *
502 * @return the receiver's parent item
503 *
504 * @exception DWTException <ul>
505 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
506 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
507 * </ul>
508 */
509 public Menu getParentMenu () {
510 checkWidget ();
511 if (cascade !is null) return cascade.parent;
512 return null;
513 }
514
515 /**
516 * Returns the receiver's shell. For all controls other than
517 * shells, this simply returns the control's nearest ancestor
518 * shell. Shells return themselves, even if they are children
519 * of other shells.
520 *
521 * @return the receiver's shell
522 *
523 * @exception DWTException <ul>
524 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
525 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
526 * </ul>
527 *
528 * @see #getParent
529 */
530 public Shell getShell () {
531 checkWidget ();
532 return parent.getShell ();
533 }
534
535 /**
536 * Returns <code>true</code> if the receiver is visible, and
537 * <code>false</code> otherwise.
538 * <p>
539 * If one of the receiver's ancestors is not visible or some
540 * other condition makes the receiver not visible, this method
541 * may still indicate that it is considered visible even though
542 * it may not actually be showing.
543 * </p>
544 *
545 * @return the receiver's visibility state
546 *
547 * @exception DWTException <ul>
548 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
549 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
550 * </ul>
551 */
552 public bool getVisible () {
553 checkWidget ();
554 if ((style & DWT.BAR) !is 0) {
555 return this is parent.menuShell ().menuBar;
556 }
557 if ((style & DWT.POP_UP) !is 0) {
558 // Menu [] popups = display.popups;
559 // if (popups is null) return false;
560 // for (int i=0; i<popups.length; i++) {
561 // if (popups [i] is this) return true;
562 // }
563 }
564 // MenuTrackingData outData = new MenuTrackingData ();
565 // return OS.GetMenuTrackingData (handle, outData) is OS.noErr;
566 return false;
567 }
568
569
570 /**
571 * Searches the receiver's list starting at the first item
572 * (index 0) until an item is found that is equal to the
573 * argument, and returns the index of that item. If no item
574 * is found, returns -1.
575 *
576 * @param item the search item
577 * @return the index of the item
578 *
579 * @exception IllegalArgumentException <ul>
580 * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
581 * </ul>
582 * @exception DWTException <ul>
583 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
584 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
585 * </ul>
586 */
587 public int indexOf (MenuItem item) {
588 checkWidget ();
589 if (item is null) error (DWT.ERROR_NULL_ARGUMENT);
590 for (int i=0; i<itemCount; i++) {
591 if (items [i] is item) return i;
592 }
593 return -1;
594 }
595
596 /**
597 * Returns <code>true</code> if the receiver is enabled and all
598 * of the receiver's ancestors are enabled, and <code>false</code>
599 * otherwise. A disabled menu is typically not selectable from the
600 * user interface and draws with an inactive or "grayed" look.
601 *
602 * @return the receiver's enabled state
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 * @see #getEnabled
610 */
611 public bool isEnabled () {
612 checkWidget ();
613 Menu parentMenu = getParentMenu ();
614 if (parentMenu is null) {
615 return getEnabled () && parent.isEnabled ();
616 }
617 return getEnabled () && parentMenu.isEnabled ();
618 }
619
620 /**
621 * Returns <code>true</code> if the receiver is visible and all
622 * of the receiver's ancestors are visible and <code>false</code>
623 * otherwise.
624 *
625 * @return the receiver's visibility state
626 *
627 * @exception DWTException <ul>
628 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
629 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
630 * </ul>
631 *
632 * @see #getVisible
633 */
634 public bool isVisible () {
635 checkWidget ();
636 return getVisible ();
637 }
638
639 void menu_willHighlightItem(int menu, int itemID) {
640 int jniRef = OS.objc_msgSend(itemID, OS.sel_tag);
641 if (jniRef !is -1 && jniRef !is 0) {
642 Object object = OS.JNIGetObject(jniRef);
643 if (object instanceof MenuItem) {
644 MenuItem item = (MenuItem)object;
645 item.sendEvent (DWT.Arm);
646 }
647 }
648 }
649
650 void menuNeedsUpdate(int menu) {
651 sendEvent (DWT.Show);
652 }
653
654 void menuWillClose(int menu) {
655 sendEvent (DWT.Hide);
656 }
657
658 void menuWillOpen(int menu) {
659 }
660
661 int modifierIndex (String accelText) {
662 int start = accelText.length () - 1;
663 int index = start;
664 while (index >= 0) {
665 char c = accelText.charAt (index);
666 switch (c) {
667 case ' ':
668 if (index !is start) return index;
669 break;
670 case '\u2303':
671 case '\u2325':
672 case '\u21E7':
673 case '\u2318':
674 return index;
675 }
676 index--;
677 }
678 return -1;
679 }
680
681 int numberOfItemsInMenu(int menu) {
682 System.out.println("numver");
683 return 4;
684 }
685
686 void releaseChildren (bool destroy) {
687 if (items !is null) {
688 for (int i=0; i<items.length; i++) {
689 MenuItem item = items [i];
690 if (item !is null && !item.isDisposed ()) {
691 item.release (false);
692 }
693 }
694 items = null;
695 }
696 super.releaseChildren (destroy);
697 }
698
699 void releaseHandle () {
700 super.releaseHandle ();
701 nsMenu = null;
702 }
703
704 void releaseParent () {
705 super.releaseParent ();
706 if (cascade !is null) cascade.setMenu (null);
707 if ((style & DWT.BAR) !is 0 && this is parent.menuBar) {
708 parent.setMenuBar (null);
709 }
710 }
711
712 void releaseWidget () {
713 super.releaseWidget ();
714 // display.removeMenu (this);
715 parent = null;
716 cascade = defaultItem = lastTarget = null;
717 }
718
719 /**
720 * Removes the listener from the collection of listeners who will
721 * be notified when the help events are generated for the control.
722 *
723 * @param listener the listener which should no longer be notified
724 *
725 * @exception IllegalArgumentException <ul>
726 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
727 * </ul>
728 * @exception DWTException <ul>
729 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
730 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
731 * </ul>
732 *
733 * @see HelpListener
734 * @see #addHelpListener
735 */
736 public void removeHelpListener (HelpListener listener) {
737 checkWidget ();
738 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
739 if (eventTable is null) return;
740 eventTable.unhook (DWT.Help, listener);
741 }
742
743 /**
744 * Removes the listener from the collection of listeners who will
745 * be notified when the menu events are generated for the control.
746 *
747 * @param listener the listener which should no longer be notified
748 *
749 * @exception IllegalArgumentException <ul>
750 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
751 * </ul>
752 * @exception DWTException <ul>
753 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
754 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
755 * </ul>
756 *
757 * @see MenuListener
758 * @see #addMenuListener
759 */
760 public void removeMenuListener (MenuListener listener) {
761 checkWidget ();
762 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
763 if (eventTable is null) return;
764 eventTable.unhook (DWT.Hide, listener);
765 eventTable.unhook (DWT.Show, listener);
766 }
767
768 /**
769 * Sets the default menu item to the argument or removes
770 * the default emphasis when the argument is <code>null</code>.
771 *
772 * @param item the default menu item or null
773 *
774 * @exception IllegalArgumentException <ul>
775 * <li>ERROR_INVALID_ARGUMENT - if the menu item has been disposed</li>
776 * </ul>
777 * @exception DWTException <ul>
778 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
779 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
780 * </ul>
781 */
782 public void setDefaultItem (MenuItem item) {
783 checkWidget();
784 if (item !is null && item.isDisposed()) error(DWT.ERROR_INVALID_ARGUMENT);
785 defaultItem = item;
786 }
787
788 /**
789 * Enables the receiver if the argument is <code>true</code>,
790 * and disables it otherwise. A disabled menu is typically
791 * not selectable from the user interface and draws with an
792 * inactive or "grayed" look.
793 *
794 * @param enabled the new enabled state
795 *
796 * @exception DWTException <ul>
797 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
798 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
799 * </ul>
800 */
801 public void setEnabled (bool enabled) {
802 checkWidget();
803 if (enabled) {
804 state &= ~DISABLED;
805 //OS.EnableMenuItem (handle, (short)0);
806 } else {
807 state |= DISABLED;
808 //OS.DisableMenuItem (handle, (short)0);
809 }
810 }
811
812 /**
813 * Sets the location of the receiver, which must be a popup,
814 * to the point specified by the arguments which are relative
815 * to the display.
816 * <p>
817 * Note that this is different from most widgets where the
818 * location of the widget is relative to the parent.
819 * </p><p>
820 * Note that the platform window manager ultimately has control
821 * over the location of popup menus.
822 * </p>
823 *
824 * @param x the new x coordinate for the receiver
825 * @param y the new y coordinate for the receiver
826 *
827 * @exception DWTException <ul>
828 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
829 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
830 * </ul>
831 */
832 public void setLocation (int x, int y) {
833 checkWidget ();
834 this.x = x;
835 this.y = y;
836 hasLocation = true;
837 }
838
839 /**
840 * Sets the location of the receiver, which must be a popup,
841 * to the point specified by the argument which is relative
842 * to the display.
843 * <p>
844 * Note that this is different from most widgets where the
845 * location of the widget is relative to the parent.
846 * </p><p>
847 * Note that the platform window manager ultimately has control
848 * over the location of popup menus.
849 * </p>
850 *
851 * @param location the new location for the receiver
852 *
853 * @exception IllegalArgumentException <ul>
854 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
855 * </ul>
856 * @exception DWTException <ul>
857 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
858 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
859 * </ul>
860 *
861 * @since 2.1
862 */
863 public void setLocation (Point location) {
864 checkWidget ();
865 if (location is null) error (DWT.ERROR_NULL_ARGUMENT);
866 setLocation (location.x, location.y);
867 }
868
869 /**
870 * Marks the receiver as visible if the argument is <code>true</code>,
871 * and marks it invisible otherwise.
872 * <p>
873 * If one of the receiver's ancestors is not visible or some
874 * other condition makes the receiver not visible, marking
875 * it visible may not actually cause it to be displayed.
876 * </p>
877 *
878 * @param visible the new visibility state
879 *
880 * @exception DWTException <ul>
881 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
882 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
883 * </ul>
884 */
885 public void setVisible (bool visible) {
886 checkWidget ();
887 if ((style & (DWT.BAR | DWT.DROP_DOWN)) !is 0) return;
888 if (visible) {
889 // display.addPopup (this);
890 //TODO -WRONG
891 _setVisible (true);
892 } else {
893 // display.removePopup (this);
894 _setVisible (false);
895 }
896 }
897
898 }