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 }