Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / libjava / javax / swing / JMenu.java
blobd9ad317a7ef8bb96e2506d85a68db32d71a5bda5
1 /* JMenu.java --
2 Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax.swing;
41 import java.awt.Component;
42 import java.awt.Point;
43 import java.awt.event.KeyEvent;
44 import java.awt.event.WindowAdapter;
45 import java.awt.event.WindowEvent;
46 import java.beans.PropertyChangeEvent;
47 import java.beans.PropertyChangeListener;
48 import java.io.IOException;
49 import java.io.ObjectOutputStream;
50 import java.io.Serializable;
51 import java.util.EventListener;
53 import javax.accessibility.Accessible;
54 import javax.accessibility.AccessibleContext;
55 import javax.accessibility.AccessibleRole;
56 import javax.accessibility.AccessibleSelection;
57 import javax.swing.event.MenuEvent;
58 import javax.swing.event.MenuListener;
59 import javax.swing.plaf.MenuItemUI;
61 /**
62 * This class represents a menu that can be added to a menu bar or
63 * can be a submenu in some other menu. When JMenu is selected it
64 * displays JPopupMenu containing its menu items.
66 * <p>
67 * JMenu's fires MenuEvents when this menu's selection changes. If this menu
68 * is selected, then fireMenuSelectedEvent() is invoked. In case when menu is
69 * deselected or cancelled, then fireMenuDeselectedEvent() or
70 * fireMenuCancelledEvent() is invoked, respectivelly.
71 * </p>
73 public class JMenu extends JMenuItem implements Accessible, MenuElement
75 private static final long serialVersionUID = 4227225638931828014L;
77 /** A Popup menu associated with this menu, which pops up when menu is selected */
78 private JPopupMenu popupMenu = new JPopupMenu();
80 /** Whenever menu is selected or deselected the MenuEvent is fired to
81 menu's registered listeners. */
82 private MenuEvent menuEvent = new MenuEvent(this);
84 /*Amount of time, in milliseconds, that should pass before popupMenu
85 associated with this menu appears or disappers */
86 private int delay;
88 /* PopupListener */
89 protected WinListener popupListener;
91 /** Location at which popup menu associated with this menu will be
92 displayed */
93 private Point menuLocation;
95 /**
96 * Creates a new JMenu object.
98 public JMenu()
100 super();
104 * Creates a new <code>JMenu</code> with the specified label.
106 * @param text label for this menu
108 public JMenu(String text)
110 super(text);
111 popupMenu.setInvoker(this);
115 * Creates a new <code>JMenu</code> object.
117 * @param action Action that is used to create menu item tha will be
118 * added to the menu.
120 public JMenu(Action action)
122 super(action);
123 createActionChangeListener(this);
124 popupMenu.setInvoker(this);
128 * Creates a new <code>JMenu</code> with specified label and an option
129 * for this menu to be tear-off menu.
131 * @param text label for this menu
132 * @param tearoff true if this menu should be tear-off and false otherwise
134 public JMenu(String text, boolean tearoff)
136 // FIXME: tearoff not implemented
137 this(text);
140 private void writeObject(ObjectOutputStream stream) throws IOException
145 * Adds specified menu item to this menu
147 * @param item Menu item to add to this menu
149 * @return Menu item that was added
151 public JMenuItem add(JMenuItem item)
153 return popupMenu.add(item);
157 * Adds specified component to this menu.
159 * @param component Component to add to this menu
161 * @return Component that was added
163 public Component add(Component component)
165 return popupMenu.add(component);
169 * Adds specified component to this menu at the given index
171 * @param component Component to add
172 * @param index Position of this menu item in the menu
174 * @return Component that was added
176 public Component add(Component component, int index)
178 return popupMenu.add(component, index);
182 * Adds JMenuItem constructed with the specified label to this menu
184 * @param text label for the menu item that will be added
186 * @return Menu Item that was added to this menu
188 public JMenuItem add(String text)
190 return popupMenu.add(text);
194 * Adds JMenuItem constructed using properties from specified action.
196 * @param action action to construct the menu item with
198 * @return Menu Item that was added to this menu
200 public JMenuItem add(Action action)
202 return popupMenu.add(action);
206 * Removes given menu item from this menu. Nothing happens if
207 * this menu doesn't contain specified menu item.
209 * @param item Menu Item which needs to be removed
211 public void remove(JMenuItem item)
213 popupMenu.remove(item);
217 * Removes component at the specified index from this menu
219 * @param index Position of the component that needs to be removed in the menu
221 public void remove(int index)
223 popupMenu.remove(index);
227 * Removes given component from this menu.
229 * @param component Component to remove
231 public void remove(Component component)
233 int index = popupMenu.getComponentIndex(component);
234 popupMenu.remove(index);
238 * Removes all menu items from the menu
240 public void removeAll()
242 popupMenu.removeAll();
246 * Creates JMenuItem with the specified text and inserts it in the
247 * at the specified index
249 * @param text label for the new menu item
250 * @param index index at which to insert newly created menu item.
252 public void insert(String text, int index)
254 this.insert(new JMenuItem(text), index);
258 * Creates JMenuItem with the specified text and inserts it in the
259 * at the specified index. IllegalArgumentException is thrown
260 * if index is less than 0
262 * @param item menu item to insert
263 * @param index index at which to insert menu item.
264 * @return Menu item that was added to the menu
266 public JMenuItem insert(JMenuItem item, int index)
268 if (index < 0)
269 throw new IllegalArgumentException("index less than zero");
271 popupMenu.insert(item, index);
272 return item;
276 * Creates JMenuItem with the associated action and inserts it to the menu
277 * at the specified index. IllegalArgumentException is thrown
278 * if index is less than 0
280 * @param action Action for the new menu item
281 * @param index index at which to insert newly created menu item.
282 * @return Menu item that was added to the menu
284 public JMenuItem insert(Action action, int index)
286 JMenuItem item = new JMenuItem(action);
287 this.insert(item, index);
289 return item;
293 * This method sets this menuItem's UI to the UIManager's default for the
294 * current look and feel.
296 public void updateUI()
298 super.setUI((MenuItemUI) UIManager.getUI(this));
299 invalidate();
303 * This method returns a name to identify which look and feel class will be
304 * the UI delegate for the menu.
306 * @return The Look and Feel classID. "MenuUI"
308 public String getUIClassID()
310 return "MenuUI";
314 * Sets model for this menu.
316 * @param model model to set
318 public void setModel(ButtonModel model)
320 super.setModel(model);
324 * Returns true if the menu is selected and false otherwise
326 * @return true if the menu is selected and false otherwise
328 public boolean isSelected()
330 return super.isArmed();
334 * Changes this menu selected state if selected is true and false otherwise
335 * This method fires menuEvents to menu's registered listeners.
337 * @param selected true if the menu should be selected and false otherwise
339 public void setSelected(boolean selected)
341 // if this menu selection is true, then activate this menu and
342 // display popup associated with this menu
343 if (selected)
345 super.setArmed(true);
346 super.setSelected(true);
348 // FIXME: The popup menu should be shown on the screen after certain
349 // number of seconds pass. The 'delay' property of this menu indicates
350 // this amount of seconds. 'delay' property is 0 by default.
351 if (this.isShowing())
353 fireMenuSelected();
355 int x = 0;
356 int y = 0;
358 if (menuLocation == null)
360 // Calculate correct position of the popup. Note that location of the popup
361 // passed to show() should be relative to the popup's invoker
362 if (isTopLevelMenu())
363 y = this.getHeight();
364 else
365 x = this.getWidth();
367 getPopupMenu().show(this, x, y);
369 else
370 getPopupMenu().show(this, menuLocation.x, menuLocation.y);
374 else
376 super.setSelected(false);
377 super.setArmed(false);
378 fireMenuDeselected();
379 popupMenu.setVisible(false);
384 * Checks if PopupMenu associated with this menu is visible
386 * @return true if the popup associated with this menu is currently visible
387 * on the screen and false otherwise.
389 public boolean isPopupMenuVisible()
391 return popupMenu.isVisible();
395 * Sets popup menu visibility
397 * @param popup true if popup should be visible and false otherwise
399 public void setPopupMenuVisible(boolean popup)
401 if (getModel().isEnabled())
402 popupMenu.setVisible(popup);
406 * Returns origin point of the popup menu
408 * @return Point containing
410 protected Point getPopupMenuOrigin()
412 // if menu in the menu bar
413 if (isTopLevelMenu())
414 return new Point(0, this.getHeight());
416 // if submenu
417 return new Point(this.getWidth(), 0);
421 * Returns delay property.
423 * @return delay property, indicating number of milliseconds before
424 * popup menu associated with the menu appears or disappears after
425 * menu was selected or deselected respectively
427 public int getDelay()
429 return delay;
433 * Sets delay property for this menu. If given time for the delay
434 * property is negative, then IllegalArgumentException is thrown
436 * @param delay number of milliseconds before
437 * popup menu associated with the menu appears or disappears after
438 * menu was selected or deselected respectively
440 public void setDelay(int delay)
442 if (delay < 0)
443 throw new IllegalArgumentException("delay less than 0");
444 this.delay = delay;
448 * Sets location at which popup menu should be displayed
449 * The location given is relative to this menu item
451 * @param x x-coordinate of the menu location
452 * @param y y-coordinate of the menu location
454 public void setMenuLocation(int x, int y)
456 menuLocation = new Point(x, y);
460 * Creates and returns JMenuItem associated with the given action
462 * @param action Action to use for creation of JMenuItem
464 * @return JMenuItem that was creted with given action
466 protected JMenuItem createActionComponent(Action action)
468 return new JMenuItem(action);
472 * Creates ActionChangeListener to listen for PropertyChangeEvents occuring
473 * in the action that is associated with this menu
475 * @param item menu that contains action to listen to
477 * @return The PropertyChangeListener
479 protected PropertyChangeListener createActionChangeListener(JMenuItem item)
481 return new ActionChangedListener(item);
485 * Adds separator to the end of the menu items in the menu.
487 public void addSeparator()
489 getPopupMenu().addSeparator();
493 * Inserts separator in the menu at the specified index.
495 * @param index Index at which separator should be inserted
497 public void insertSeparator(int index)
499 if (index < 0)
500 throw new IllegalArgumentException("index less than 0");
502 getPopupMenu().insert(new JPopupMenu.Separator(), index);
506 * Returns menu item located at the specified index in the menu
508 * @param index Index at which to look for the menu item
510 * @return menu item located at the specified index in the menu
512 public JMenuItem getItem(int index)
514 if (index < 0)
515 throw new IllegalArgumentException("index less than 0");
517 Component c = popupMenu.getComponentAtIndex(index);
519 if (c instanceof JMenuItem)
520 return (JMenuItem) c;
521 else
522 return null;
526 * Returns number of items in the menu including separators.
528 * @return number of items in the menu
530 * @see #getMenuComponentCount()
532 public int getItemCount()
534 return getMenuComponentCount();
538 * Checks if this menu is a tear-off menu.
540 * @return true if this menu is a tear-off menu and false otherwise
542 public boolean isTearOff()
544 // NOT YET IMPLEMENTED
545 return false;
549 * Returns number of menu components in this menu
551 * @return number of menu components in this menu
553 public int getMenuComponentCount()
555 return popupMenu.getComponentCount();
559 * Returns menu component located at the givent index
560 * in the menu
562 * @param index index at which to get the menu component in the menu
564 * @return Menu Component located in the menu at the specified index
566 public Component getMenuComponent(int index)
568 return (Component) popupMenu.getComponentAtIndex(index);
572 * Return components belonging to this menu
574 * @return components belonging to this menu
576 public Component[] getMenuComponents()
578 return popupMenu.getComponents();
582 * Checks if this menu is a top level menu. The menu is top
583 * level menu if it is inside the menu bar. While if the menu
584 * inside some other menu, it is considered to be a pull-right menu.
586 * @return true if this menu is top level menu, and false otherwise
588 public boolean isTopLevelMenu()
590 return getParent() instanceof JMenuBar;
594 * Checks if given component exists in this menu. The submenus of
595 * this menu are checked as well
597 * @param component Component to look for
599 * @return true if the given component exists in this menu, and false otherwise
601 public boolean isMenuComponent(Component component)
603 return false;
607 * Returns popup menu associated with the menu.
609 * @return popup menu associated with the menu.
611 public JPopupMenu getPopupMenu()
613 return popupMenu;
617 * Adds MenuListener to the menu
619 * @param listener MenuListener to add
621 public void addMenuListener(MenuListener listener)
623 listenerList.add(MenuListener.class, listener);
627 * Removes MenuListener from the menu
629 * @param listener MenuListener to remove
631 public void removeMenuListener(MenuListener listener)
633 listenerList.remove(MenuListener.class, listener);
637 * Returns all registered <code>MenuListener</code> objects.
639 * @return an array of listeners
641 * @since 1.4
643 public MenuListener[] getMenuListeners()
645 return (MenuListener[]) listenerList.getListeners(MenuListener.class);
649 * This method fires MenuEvents to all menu's MenuListeners. In this case
650 * menuSelected() method of MenuListeners is called to indicated that the menu
651 * was selected.
653 protected void fireMenuSelected()
655 MenuListener[] listeners = getMenuListeners();
657 for (int index = 0; index < listeners.length; ++index)
658 listeners[index].menuSelected(menuEvent);
662 * This method fires MenuEvents to all menu's MenuListeners. In this case
663 * menuDeselected() method of MenuListeners is called to indicated that the menu
664 * was deselected.
666 protected void fireMenuDeselected()
668 EventListener[] ll = listenerList.getListeners(MenuListener.class);
670 for (int i = 0; i < ll.length; i++)
671 ((MenuListener) ll[i]).menuDeselected(menuEvent);
675 * This method fires MenuEvents to all menu's MenuListeners. In this case
676 * menuSelected() method of MenuListeners is called to indicated that the menu
677 * was cancelled. The menu is cancelled when it's popup menu is close without selection.
679 protected void fireMenuCanceled()
681 EventListener[] ll = listenerList.getListeners(MenuListener.class);
683 for (int i = 0; i < ll.length; i++)
684 ((MenuListener) ll[i]).menuCanceled(menuEvent);
688 * Creates WinListener that listens to the menu;s popup menu.
690 * @param popup JPopupMenu to listen to
692 * @return The WinListener
694 protected WinListener createWinListener(JPopupMenu popup)
696 return new WinListener(popup);
700 * Method of the MenuElementInterface. It reacts to the selection
701 * changes in the menu. If this menu was selected, then it
702 * displayes popup menu associated with it and if this menu was
703 * deselected it hides the popup menu.
705 * @param changed true if the menu was selected and false otherwise
707 public void menuSelectionChanged(boolean changed)
709 // if this menu selection is true, then activate this menu and
710 // display popup associated with this menu
711 setSelected(changed);
715 * Method of MenuElement interface. Returns sub components of
716 * this menu.
718 * @return array containing popupMenu that is associated with this menu
720 public MenuElement[] getSubElements()
722 return new MenuElement[] { popupMenu };
726 * @return Returns reference to itself
728 public Component getComponent()
730 return this;
734 * This method is overriden with empty implementation, s.t the
735 * accelerator couldn't be set for the menu. The mnemonic should
736 * be used for the menu instead.
738 * @param keystroke accelerator for this menu
740 public void setAccelerator(KeyStroke keystroke)
742 throw new Error("setAccelerator() is not defined for JMenu. Use setMnemonic() instead.");
746 * This method process KeyEvent occuring when the menu is visible
748 * @param event The KeyEvent
750 protected void processKeyEvent(KeyEvent event)
755 * Programatically performs click
757 * @param time Number of milliseconds for which this menu stays pressed
759 public void doClick(int time)
761 getModel().setArmed(true);
762 getModel().setPressed(true);
765 java.lang.Thread.sleep(time);
767 catch (java.lang.InterruptedException e)
769 // probably harmless
772 getModel().setPressed(false);
773 getModel().setArmed(false);
774 popupMenu.show(this, this.getWidth(), 0);
778 * A string that describes this JMenu. Normally only used
779 * for debugging.
781 * @return A string describing this JMenu
783 protected String paramString()
785 return super.paramString();
788 public AccessibleContext getAccessibleContext()
790 if (accessibleContext == null)
791 accessibleContext = new AccessibleJMenu();
793 return accessibleContext;
796 protected class AccessibleJMenu extends AccessibleJMenuItem
797 implements AccessibleSelection
799 protected AccessibleJMenu()
803 public int getAccessibleChildrenCount()
805 return 0;
808 public Accessible getAccessibleChild(int value0)
810 return null;
813 public AccessibleSelection getAccessibleSelection()
815 return null;
818 public Accessible getAccessibleSelection(int value0)
820 return null;
823 public boolean isAccessibleChildSelected(int value0)
825 return false;
828 public AccessibleRole getAccessibleRole()
830 return AccessibleRole.MENU;
833 public int getAccessibleSelectionCount()
835 return 0;
838 public void addAccessibleSelection(int value0)
842 public void removeAccessibleSelection(int value0)
846 public void clearAccessibleSelection()
850 public void selectAllAccessibleSelection()
855 protected class WinListener extends WindowAdapter implements Serializable
857 JPopupMenu popupMenu;
858 private static final long serialVersionUID = -6415815570638474823L;
860 public WinListener(JPopupMenu popup)
864 public void windowClosing(WindowEvent event)
870 * This class listens to PropertyChangeEvents occuring in menu's action
872 protected class ActionChangedListener implements PropertyChangeListener
874 /** menu item associated with the action */
875 private JMenuItem menuItem;
877 /** Creates new ActionChangedListener and adds it to menuItem's action */
878 public ActionChangedListener(JMenuItem menuItem)
880 this.menuItem = menuItem;
882 Action a = menuItem.getAction();
883 if (a != null)
884 a.addPropertyChangeListener(this);
887 /**This method is invoked when some change occures in menuItem's action*/
888 public void propertyChange(PropertyChangeEvent evt)
890 // FIXME: Need to implement