Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/eclipse/swt/widgets/Menu.java


1   /*******************************************************************************
2    * Copyright (c) 2000, 2004 IBM Corporation and others.
3    * All rights reserved. This program and the accompanying materials
4    * are made available under the terms of the Common Public License v1.0
5    * which accompanies this distribution, and is available at
6    * http://www.eclipse.org/legal/cpl-v10.html
7    * 
8    * Contributors:
9    *     IBM Corporation - initial API and implementation
10   *******************************************************************************/
11  package org.eclipse.swt.widgets;
12  
13  
14  import org.eclipse.swt.internal.*;
15  import org.eclipse.swt.internal.gtk.*;
16  import org.eclipse.swt.*;
17  import org.eclipse.swt.events.*;
18  import org.eclipse.swt.graphics.*;
19  
20  /**
21   * Instances of this class are user interface objects that contain
22   * menu items.
23   * <dl>
24   * <dt><b>Styles:</b></dt>
25   * <dd>BAR, DROP_DOWN, POP_UP, NO_RADIO_GROUP</dd>
26   * <dd>LEFT_TO_RIGHT, RIGHT_TO_LEFT</dd>
27   * <dt><b>Events:</b></dt>
28   * <dd>Help, Hide, Show </dd>
29   * </dl>
30   * <p>
31   * Note: Only one of BAR, DROP_DOWN and POP_UP may be specified.
32   * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified.
33   * </p><p>
34   * IMPORTANT: This class is <em>not</em> intended to be subclassed.
35   * </p>
36   */
37  public class Menu extends Widget {
38    int x, y;
39    boolean hasLocation;
40    MenuItem cascade, selectedItem;
41    Decorations parent;
42    long /*int*/ imItem, imSeparator, imHandle;
43  
44  /**
45   * Constructs a new instance of this class given its parent,
46   * and sets the style for the instance so that the instance
47   * will be a popup menu on the given parent's shell.
48   *
49   * @param parent a control which will be the parent of the new instance (cannot be null)
50   *
51   * @exception IllegalArgumentException <ul>
52   *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
53   * </ul>
54   * @exception SWTException <ul>
55   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
56   *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
57   * </ul>
58   *
59   * @see SWT#POP_UP
60   * @see Widget#checkSubclass
61   * @see Widget#getStyle
62   */
63  public Menu (Control parent) {
64    this (checkNull (parent).menuShell (), SWT.POP_UP);
65  }
66  
67  /**
68   * Constructs a new instance of this class given its parent
69   * (which must be a <code>Decorations</code>) and a style value
70   * describing its behavior and appearance.
71   * <p>
72   * The style value is either one of the style constants defined in
73   * class <code>SWT</code> which is applicable to instances of this
74   * class, or must be built by <em>bitwise OR</em>'ing together 
75   * (that is, using the <code>int</code> "|" operator) two or more
76   * of those <code>SWT</code> style constants. The class description
77   * lists the style constants that are applicable to the class.
78   * Style bits are also inherited from superclasses.
79   * </p>
80   *
81   * @param parent a decorations control which will be the parent of the new instance (cannot be null)
82   * @param style the style of menu to construct
83   *
84   * @exception IllegalArgumentException <ul>
85   *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
86   * </ul>
87   * @exception SWTException <ul>
88   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
89   *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
90   * </ul>
91   *
92   * @see SWT#BAR
93   * @see SWT#DROP_DOWN
94   * @see SWT#POP_UP
95   * @see Widget#checkSubclass
96   * @see Widget#getStyle
97   */
98  public Menu (Decorations parent, int style) {
99    super (parent, checkStyle (style));
100   this.parent = parent;
101   createWidget (0);
102 }
103 
104 /**
105  * Constructs a new instance of this class given its parent
106  * (which must be a <code>Menu</code>) and sets the style
107  * for the instance so that the instance will be a drop-down
108  * menu on the given parent's parent.
109  *
110  * @param parentMenu a menu which will be the parent of the new instance (cannot be null)
111  *
112  * @exception IllegalArgumentException <ul>
113  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
114  * </ul>
115  * @exception SWTException <ul>
116  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
117  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
118  * </ul>
119  *
120  * @see SWT#DROP_DOWN
121  * @see Widget#checkSubclass
122  * @see Widget#getStyle
123  */
124 public Menu (Menu parentMenu) {
125   this (checkNull (parentMenu).parent, SWT.DROP_DOWN);
126 }
127 
128 /**
129  * Constructs a new instance of this class given its parent
130  * (which must be a <code>MenuItem</code>) and sets the style
131  * for the instance so that the instance will be a drop-down
132  * menu on the given parent's parent menu.
133  *
134  * @param parentItem a menu item which will be the parent of the new instance (cannot be null)
135  *
136  * @exception IllegalArgumentException <ul>
137  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
138  * </ul>
139  * @exception SWTException <ul>
140  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
141  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
142  * </ul>
143  *
144  * @see SWT#DROP_DOWN
145  * @see Widget#checkSubclass
146  * @see Widget#getStyle
147  */
148 public Menu (MenuItem parentItem) {
149   this (checkNull (parentItem).parent);
150 }
151 
152 static Control checkNull (Control control) {
153   if (control == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
154   return control;
155 }
156 
157 static Menu checkNull (Menu menu) {
158   if (menu == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
159   return menu;
160 }
161 
162 static MenuItem checkNull (MenuItem item) {
163   if (item == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
164   return item;
165 }
166 
167 static int checkStyle (int style) {
168   return checkBits (style, SWT.POP_UP, SWT.BAR, SWT.DROP_DOWN, 0, 0, 0);
169 }
170 
171 public void _setVisible (boolean visible) {
172   if (visible == OS.GTK_WIDGET_MAPPED (handle)) return;
173   if (visible) {
174     sendEvent (SWT.Show);
175     if (getItemCount () != 0) {
176       long /*int*/ address = 0;
177       if (hasLocation) address = display.menuPositionProc;
178       OS.gtk_menu_popup (handle, 0, 0, address, 0, 0, display.popupTime);
179     } else {
180       sendEvent (SWT.Hide);
181     }
182   } else {
183     OS.gtk_menu_popdown (handle);
184   }
185 }
186 
187 void addAccelerators (long /*int*/ accelGroup) {
188   MenuItem [] items = getItems ();
189   for (int i = 0; i < items.length; i++) {
190     MenuItem item = items[i];
191     item.addAccelerators (accelGroup);
192   }
193 }
194 
195 /**
196  * Adds the listener to the collection of listeners who will
197  * be notified when menus are hidden or shown, by sending it
198  * one of the messages defined in the <code>MenuListener</code>
199  * interface.
200  *
201  * @param listener the listener which should be notified
202  *
203  * @exception IllegalArgumentException <ul>
204  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
205  * </ul>
206  * @exception SWTException <ul>
207  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
208  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
209  * </ul>
210  *
211  * @see MenuListener
212  * @see #removeMenuListener
213  */
214 public void addMenuListener (MenuListener listener) {
215   checkWidget();
216   if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
217   TypedListener typedListener = new TypedListener (listener);
218   addListener (SWT.Hide,typedListener);
219   addListener (SWT.Show,typedListener);
220 }
221 
222 /**
223  * Adds the listener to the collection of listeners who will
224  * be notified when help events are generated for the control,
225  * by sending it one of the messages defined in the
226  * <code>HelpListener</code> interface.
227  *
228  * @param listener the listener which should be notified
229  *
230  * @exception IllegalArgumentException <ul>
231  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
232  * </ul>
233  * @exception SWTException <ul>
234  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
235  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
236  * </ul>
237  *
238  * @see HelpListener
239  * @see #removeHelpListener
240  */
241 public void addHelpListener (HelpListener listener) {
242   checkWidget();
243   if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
244   TypedListener typedListener = new TypedListener (listener);
245   addListener (SWT.Help, typedListener);
246 }
247 
248 void createHandle (int index) {
249   state |= HANDLE;
250   if ((style & SWT.BAR) != 0) {
251     handle = OS.gtk_menu_bar_new ();
252     if (handle == 0) error (SWT.ERROR_NO_HANDLES);
253     long /*int*/ parentHandle = parent.fixedHandle;
254     OS.gtk_container_add (parentHandle, handle);
255   } else {
256     handle = OS.gtk_menu_new ();
257     if (handle == 0) error (SWT.ERROR_NO_HANDLES);
258   }
259 }
260 
261 void createIMMenu (long /*int*/ imHandle) {
262   if (this.imHandle == imHandle) return;
263   this.imHandle = imHandle;
264   if (imHandle == 0) {
265     if (imItem != 0) {
266       OS.gtk_widget_destroy (imItem);
267       imItem = 0;
268     }
269     if (imSeparator != 0) {
270       OS.gtk_widget_destroy (imSeparator);
271       imSeparator = 0;
272     }
273     return;
274   } 
275   if (imSeparator == 0) {
276     imSeparator = OS.gtk_separator_menu_item_new ();
277     OS.gtk_widget_show (imSeparator);
278     OS.gtk_menu_shell_insert (handle, imSeparator, -1);
279   }
280   if (imItem == 0) {
281     byte[] buffer = Converter.wcsToMbcs (null, SWT.getMessage("SWT_InputMethods"), true);
282     imItem = OS.gtk_image_menu_item_new_with_label (buffer);
283     OS.gtk_widget_show (imItem);
284     OS.gtk_menu_shell_insert (handle, imItem, -1);
285   }
286   long /*int*/ imSubmenu = OS.gtk_menu_new ();
287   OS.gtk_im_multicontext_append_menuitems (imHandle, imSubmenu);
288   OS.gtk_menu_item_set_submenu (imItem, imSubmenu);
289 }
290 
291 void createWidget (int index) {
292   checkOrientation (parent);
293   super.createWidget (index);
294   parent.add (this);
295 }
296 
297 void fixMenus (Decorations newParent) {
298   MenuItem [] items = getItems ();
299   for (int i=0; i<items.length; i++) {
300     items [i].fixMenus (newParent);
301   }
302   parent.remove (this);
303   newParent.add (this);
304   this.parent = newParent;
305 }
306 
307 /**
308  * Returns the default menu item or null if none has
309  * been previously set.
310  *
311  * @return the default menu item.
312  *
313  * </ul>
314  * @exception SWTException <ul>
315  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
316  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
317  * </ul>
318  */
319 public MenuItem getDefaultItem () {
320   checkWidget();
321   return null;
322 }
323 
324 /**
325  * Returns <code>true</code> if the receiver is enabled, and
326  * <code>false</code> otherwise. A disabled control is typically
327  * not selectable from the user interface and draws with an
328  * inactive or "grayed" look.
329  *
330  * @return the receiver's enabled state
331  *
332  * @exception SWTException <ul>
333  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
334  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
335  * </ul>
336  * 
337  * @see #isEnabled
338  */
339 public boolean getEnabled () {
340   checkWidget();
341   return OS.GTK_WIDGET_SENSITIVE (handle);     
342 }
343 
344 /**
345  * Returns the item at the given, zero-relative index in the
346  * receiver. Throws an exception if the index is out of range.
347  *
348  * @param index the index of the item to return
349  * @return the item at the given index
350  *
351  * @exception IllegalArgumentException <ul>
352  *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
353  * </ul>
354  * @exception SWTException <ul>
355  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
356  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
357  * </ul>
358  */
359 public MenuItem getItem (int index) {
360   checkWidget();
361   long /*int*/ list = OS.gtk_container_get_children (handle);
362   if (list == 0) error (SWT.ERROR_CANNOT_GET_ITEM);
363   int count = OS.g_list_length (list);
364   if (imSeparator != 0) count--;
365   if (imItem != 0) count--;
366   if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
367   long /*int*/ data = OS.g_list_nth_data (list, index);
368   OS.g_list_free (list);
369   if (data == 0) error (SWT.ERROR_CANNOT_GET_ITEM);
370   return (MenuItem) display.getWidget (data);
371 }
372 
373 /**
374  * Returns the number of items contained in the receiver.
375  *
376  * @return the number of items
377  *
378  * @exception SWTException <ul>
379  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
380  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
381  * </ul>
382  */
383 public int getItemCount () {
384   checkWidget();
385   long /*int*/ list = OS.gtk_container_get_children (handle);
386   if (list == 0) return 0;
387   int count = OS.g_list_length (list);
388   OS.g_list_free (list);
389   if (imSeparator != 0) count--;
390   if (imItem != 0) count--;
391   return count;
392 }
393 
394 /**
395  * Returns an array of <code>MenuItem</code>s which are the items
396  * in the receiver. 
397  * <p>
398  * Note: This is not the actual structure used by the receiver
399  * to maintain its list of items, so modifying the array will
400  * not affect the receiver. 
401  * </p>
402  *
403  * @return the items in the receiver
404  *
405  * @exception SWTException <ul>
406  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
407  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
408  * </ul>
409  */
410 public MenuItem [] getItems () {
411   checkWidget();
412   long /*int*/ list = OS.gtk_container_get_children (handle);
413   if (list == 0) return new MenuItem [0];
414   int count = OS.g_list_length (list);
415   if (imSeparator != 0) count--;
416   if (imItem != 0) count--;
417   MenuItem [] items = new MenuItem [count];
418   for (int i=0; i<count; i++) {
419     long /*int*/ data = OS.g_list_nth_data (list, i);
420     items [i] = (MenuItem) display.getWidget (data);
421   }
422   OS.g_list_free (list);
423   return items;
424 }
425 
426 String getNameText () {
427   String result = "";
428   MenuItem [] items = getItems ();
429   int length = items.length;
430   if (length > 0) {
431     for (int i=0; i<length-1; i++) {
432       result = result + items [i].getNameText() + ", ";
433     }
434     result = result + items [length-1].getNameText ();
435   }
436   return result;
437 }
438 
439 /**
440  * Returns the receiver's parent, which must be a <code>Decorations</code>.
441  *
442  * @return the receiver's parent
443  *
444  * @exception SWTException <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 public Decorations getParent () {
450   checkWidget();
451   return parent;
452 }
453 
454 /**
455  * Returns the receiver's parent item, which must be a
456  * <code>MenuItem</code> or null when the receiver is a
457  * root.
458  *
459  * @return the receiver's parent item
460  *
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 public MenuItem getParentItem () {
467   checkWidget();
468   return cascade;
469 }
470 
471 /**
472  * Returns the receiver's parent item, which must be a
473  * <code>Menu</code> or null when the receiver is a
474  * root.
475  *
476  * @return the receiver's parent item
477  *
478  * @exception SWTException <ul>
479  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
480  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
481  * </ul>
482  */
483 public Menu getParentMenu () {
484   checkWidget();
485   if (cascade == null) return null;
486   return cascade.getParent ();
487 }
488 
489 /**
490  * Returns the receiver's shell. For all controls other than
491  * shells, this simply returns the control's nearest ancestor
492  * shell. Shells return themselves, even if they are children
493  * of other shells.
494  *
495  * @return the receiver's shell
496  *
497  * @exception SWTException <ul>
498  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
499  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
500  * </ul>
501  *
502  * @see #getParent
503  */
504 public Shell getShell () {
505   checkWidget();
506   return parent.getShell ();
507 }
508 
509 /*public*/ Point getSize () {
510   checkWidget();
511   int width = OS.GTK_WIDGET_WIDTH (handle);
512   int height = OS.GTK_WIDGET_HEIGHT (handle);
513   return new Point (width, height);
514 }
515 
516 /**
517  * Returns <code>true</code> if the receiver is visible, and
518  * <code>false</code> otherwise.
519  * <p>
520  * If one of the receiver's ancestors is not visible or some
521  * other condition makes the receiver not visible, this method
522  * may still indicate that it is considered visible even though
523  * it may not actually be showing.
524  * </p>
525  *
526  * @return the receiver's visibility state
527  *
528  * @exception SWTException <ul>
529  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
530  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
531  * </ul>
532  */
533 public boolean getVisible () {
534   checkWidget();
535   if ((style & SWT.POP_UP) != 0) {
536     Menu [] popups = display.popups;
537     if (popups != null) {
538       for (int i=0; i<popups.length; i++) {
539         if (popups [i] == this) return true;
540       }
541     }
542   }
543   return OS.GTK_WIDGET_MAPPED (handle);
544 }
545 
546 long /*int*/ gtk_hide (long /*int*/ widget) {
547   if ((style & SWT.POP_UP) != 0) {
548     Shell shell = getShell ();
549     shell.hasFocus = true;
550   }
551   sendEvent (SWT.Hide);
552   return 0;
553 }
554 
555 long /*int*/ gtk_show (long /*int*/ widget) {
556   if ((style & SWT.POP_UP) != 0) {
557     Shell shell = getShell ();
558     shell.hasFocus = true;
559     return 0;
560   } 
561   sendEvent (SWT.Show);
562   return 0;
563 }
564 
565 
566 long /*int*/ gtk_show_help (long /*int*/ widget, long /*int*/ helpType) {
567   if (sendHelpEvent (helpType)) {
568     OS.gtk_menu_shell_deactivate (handle);
569     return 1;
570   }
571   return 0;
572 }
573 
574 void hookEvents () {
575   super.hookEvents ();
576   long /*int*/ windowProc2 = display.windowProc2;
577   long /*int*/ windowProc3 = display.windowProc3;
578   OS.g_signal_connect (handle, OS.show, windowProc2, SHOW);
579   OS.g_signal_connect (handle, OS.hide, windowProc2, HIDE);
580   OS.g_signal_connect (handle, OS.show_help, windowProc3, SHOW_HELP);
581 }
582 
583 /**
584  * Searches the receiver's list starting at the first item
585  * (index 0) until an item is found that is equal to the 
586  * argument, and returns the index of that item. If no item
587  * is found, returns -1.
588  *
589  * @param item the search item
590  * @return the index of the item
591  *
592  * @exception IllegalArgumentException <ul>
593  *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
594  * </ul>
595  * @exception SWTException <ul>
596  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
597  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
598  * </ul>
599  */
600 public int indexOf (MenuItem item) {
601   checkWidget();
602   if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
603   MenuItem [] items = getItems ();
604   for (int i=0; i<items.length; i++) {
605     if (items [i] == item) return i;
606   }
607   return -1;
608 }
609 
610 /**
611  * Returns <code>true</code> if the receiver is enabled and all
612  * of the receiver's ancestors are enabled, and <code>false</code>
613  * otherwise. A disabled control is typically not selectable from the
614  * user interface and draws with an inactive or "grayed" look.
615  *
616  * @return the receiver's enabled state
617  *
618  * @exception SWTException <ul>
619  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
620  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
621  * </ul>
622  * 
623  * @see #getEnabled
624  */
625 public boolean isEnabled () {
626   checkWidget();
627   Menu parentMenu = getParentMenu ();
628   if (parentMenu == null) return getEnabled ();
629   return getEnabled () && parentMenu.isEnabled ();
630 }
631 
632 /**
633  * Returns <code>true</code> if the receiver is visible and all
634  * of the receiver's ancestors are visible and <code>false</code>
635  * otherwise.
636  *
637  * @return the receiver's visibility state
638  *
639  * @exception SWTException <ul>
640  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
641  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
642  * </ul>
643  *
644  * @see #getVisible
645  */
646 public boolean isVisible () {
647   checkWidget();
648   return getVisible ();
649 }
650 
651 long /*int*/ menuPositionProc (long /*int*/ menu, long /*int*/ x, long /*int*/ y, long /*int*/ push_in, long /*int*/ user_data) {
652   if (x != 0) OS.memmove (x, new int [] {this.x}, 4);
653   if (y != 0) OS.memmove (y, new int [] {this.y}, 4);
654   if (push_in != 0) OS.memmove (push_in, new int [] {1}, 4);
655   return 0;
656 }
657 
658 void releaseChild () {
659   super.releaseChild ();
660   if (cascade != null) cascade.setMenu (null);
661   if ((style & SWT.BAR) != 0 && this == parent.menuBar) {
662     parent.setMenuBar (null);
663   }  else {
664     if ((style & SWT.POP_UP) != 0) {
665       display.removePopup (this);
666     }
667   }
668 }
669 
670 void releaseWidget () {
671   MenuItem [] items = getItems ();
672   for (int i=0; i<items.length; i++) {
673     MenuItem item = items [i];
674     if (!item.isDisposed ()) item.releaseResources ();
675   }
676   if (parent != null) parent.remove (this);
677   super.releaseWidget ();
678   parent = null;
679   cascade = null;
680   imItem = imSeparator = imHandle = 0;
681 }
682 
683 /**
684  * Removes the listener from the collection of listeners who will
685  * be notified when the menu events are generated for the control.
686  *
687  * @param listener the listener which should be notified
688  *
689  * @exception IllegalArgumentException <ul>
690  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
691  * </ul>
692  * @exception SWTException <ul>
693  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
694  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
695  * </ul>
696  *
697  * @see MenuListener
698  * @see #addMenuListener
699  */
700 public void removeMenuListener (MenuListener listener) {
701   checkWidget();
702   if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
703   if (eventTable == null) return;
704   eventTable.unhook (SWT.Hide, listener);
705   eventTable.unhook (SWT.Show, listener);
706 }
707 
708 void removeAccelerators (long /*int*/ accelGroup) {
709   MenuItem [] items = getItems ();
710   for (int i = 0; i < items.length; i++) {
711     MenuItem item = items[i];
712     item.removeAccelerators (accelGroup);
713   }
714 }
715 
716 /**
717  * Removes the listener from the collection of listeners who will
718  * be notified when the help events are generated for the control.
719  *
720  * @param listener the listener which should be notified
721  *
722  * @exception IllegalArgumentException <ul>
723  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
724  * </ul>
725  * @exception SWTException <ul>
726  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
727  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
728  * </ul>
729  *
730  * @see HelpListener
731  * @see #addHelpListener
732  */
733 public void removeHelpListener (HelpListener listener) {
734   checkWidget();
735   if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
736   if (eventTable == null) return;
737   eventTable.unhook (SWT.Help, listener);
738 }
739 
740 boolean sendHelpEvent (long /*int*/ helpType) {
741   if (selectedItem != null && !selectedItem.isDisposed()) {
742     if (selectedItem.hooks (SWT.Help)) {
743       selectedItem.postEvent (SWT.Help);
744       return true;
745     }
746   }
747   if (hooks (SWT.Help)) {
748     postEvent (SWT.Help);
749     return true;
750   }
751   return parent.sendHelpEvent (helpType);
752 }
753 
754 /**
755  * Sets the default menu item to the argument or removes
756  * the default emphasis when the argument is <code>null</code>.
757  * 
758  * @param item the default menu item or null
759  *
760  * @exception IllegalArgumentException <ul>
761  *    <li>ERROR_INVALID_ARGUMENT - if the menu item has been disposed</li> 
762  * </ul>
763  * @exception SWTException <ul>
764  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
765  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
766  * </ul>
767  */
768 public void setDefaultItem (MenuItem item) {
769   checkWidget();
770 }
771 
772 /**
773  * Enables the receiver if the argument is <code>true</code>,
774  * and disables it otherwise. A disabled control is typically
775  * not selectable from the user interface and draws with an
776  * inactive or "grayed" look.
777  *
778  * @param enabled the new enabled state
779  *
780  * @exception SWTException <ul>
781  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
782  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
783  * </ul>
784  */
785 public void setEnabled (boolean enabled) {
786   checkWidget();
787   if (enabled) {
788     OS.GTK_WIDGET_SET_FLAGS (handle, OS.GTK_SENSITIVE);
789   } else {
790     OS.GTK_WIDGET_UNSET_FLAGS (handle, OS.GTK_SENSITIVE);
791   }
792 }
793 
794 /**
795  * Sets the receiver's location to the point specified by
796  * the arguments which are relative to the display.
797  * <p>
798  * Note:  This is different from most widgets where the
799  * location of the widget is relative to the parent.
800  * </p>
801  *
802  * @param x the new x coordinate for the receiver
803  * @param y the new y coordinate for the receiver
804  *
805  * @exception SWTException <ul>
806  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
807  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
808  * </ul>
809  */
810 public void setLocation (int x, int y) {
811   checkWidget();
812   if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return;
813   this.x = x;
814   this.y = y;
815   hasLocation = true;  
816 }
817 
818 /**
819  * Sets the receiver's location to the point specified by
820  * the arguments which are relative to the display.
821  * <p>
822  * Note:  This is different from most widgets where the
823  * location of the widget is relative to the parent.
824  * </p>
825  *
826  * @param location the new location for the receiver
827  *
828  * @exception IllegalArgumentException <ul>
829  *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
830  * </ul>
831  * @exception SWTException <ul>
832  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
833  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
834  * </ul>
835  * 
836  * @since 2.1
837  */
838 public void setLocation (Point location) {
839   checkWidget();
840   if (location == null) error (SWT.ERROR_NULL_ARGUMENT);
841   setLocation (location.x, location.y);
842 }
843 
844 /**
845  * Marks the receiver as visible if the argument is <code>true</code>,
846  * and marks it invisible otherwise. 
847  * <p>
848  * If one of the receiver's ancestors is not visible or some
849  * other condition makes the receiver not visible, marking
850  * it visible may not actually cause it to be displayed.
851  * </p>
852  *
853  * @param visible the new visibility state
854  *
855  * @exception SWTException <ul>
856  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
857  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
858  * </ul>
859  */
860 public void setVisible (boolean visible) {
861   checkWidget();
862   if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return;
863   if (visible) {
864     display.popupTime = OS.gtk_get_current_event_time();
865     display.addPopup (this);
866   } else {
867     display.removePopup (this);
868     _setVisible (false);
869   }
870 }
871 }