2004-08-12 Janis Johnson <janis187@us.ibm.com>
[official-gcc.git] / libjava / javax / swing / JMenu.java
blob60e94418d40ffd9c1ca948cf3ce28d9cc5c76211
1 /* JMenu.java --
2 Copyright (C) 2002, 2004 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. */
38 package javax.swing;
40 import java.awt.Component;
41 import java.awt.Point;
42 import java.awt.Window;
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;
52 import java.util.Hashtable;
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.ChangeEvent;
58 import javax.swing.event.ChangeListener;
59 import javax.swing.event.MenuEvent;
60 import javax.swing.event.MenuListener;
61 import javax.swing.plaf.MenuItemUI;
64 /**
65 * <p>
66 * This class represents a menu that can be added to a menu bar or
67 * can be a submenu in some other menu. When JMenu is selected it
68 * displays JPopupMenu containing its menu items.
69 * </p>
71 * <p>
72 * JMenu's fires MenuEvents when this menu's selection changes. If this menu
73 * is selected, then fireMenuSelectedEvent() is invoked. In case when menu is
74 * deselected or cancelled, then fireMenuDeselectedEvent() or
75 * fireMenuCancelledEvent() is invoked, respectivelly.
76 * </p>
79 public class JMenu extends JMenuItem implements Accessible, MenuElement
81 static final long serialVersionUID = 4227225638931828014L;
83 /** name for the UI delegate for this menu. */
84 private static final String uiClassID = "MenuUI";
86 /** A Popup menu associated with this menu, which pops up when menu is selected */
87 private JPopupMenu popupMenu = new JPopupMenu();
89 /** Whenever menu is selected or deselected the MenuEvent is fired to
90 menu's registered listeners. */
91 private MenuEvent menuEvent = new MenuEvent(this);
93 /*Amount of time, in milliseconds, that should pass before popupMenu
94 associated with this menu appears or disappers */
95 private int delay;
97 /* PopupListener */
98 protected WinListener popupListener;
100 /** Location at which popup menu associated with this menu will be
101 displayed */
102 private Point menuLocation;
105 * Creates a new JMenu object.
107 public JMenu()
109 super();
113 * Creates a new JMenu with the spicified label
115 * @param text label for this menu
117 public JMenu(String text)
119 super(text);
123 * Creates a new JMenu object
125 * @param action Action that is used to create menu item tha will be
126 * added to the menu.
128 public JMenu(Action action)
130 super(action);
131 createActionChangeListener(this);
135 * Creates a new JMenu with specified label and an option
136 * for this menu to be tear-off menu
138 * @param text label for this menu
139 * @param tearoff true if this menu should be tear-off and false otherwise
141 public JMenu(String text, boolean tearoff)
143 throw new Error("not implemented");
146 private void writeObject(ObjectOutputStream stream) throws IOException
151 * Adds specified menu item to this menu
153 * @param item Menu item to add to this menu
155 * @return Menu item that was added
157 public JMenuItem add(JMenuItem item)
159 return popupMenu.add(item);
163 * Adds specified component to this menu.
165 * @param component Component to add to this menu
167 * @return Component that was added
169 public Component add(Component component)
171 return popupMenu.add(component);
175 * Adds specified component to this menu at the given index
177 * @param component Component to add
178 * @param index Position of this menu item in the menu
180 * @return Component that was added
182 public Component add(Component component, int index)
184 return popupMenu.add(component, index);
188 * Adds JMenuItem constructed with the specified label to this menu
190 * @param text label for the menu item that will be added
192 * @return Menu Item that was added to this menu
194 public JMenuItem add(String text)
196 return popupMenu.add(text);
200 * Adds JMenuItem constructed using properties from specified action.
202 * @param action action to construct the menu item with
204 * @return Menu Item that was added to this menu
206 public JMenuItem add(Action action)
208 return popupMenu.add(action);
212 * Removes given menu item from this menu. Nothing happens if
213 * this menu doesn't contain specified menu item.
215 * @param item Menu Item which needs to be removed
217 public void remove(JMenuItem item)
219 popupMenu.remove(item);
223 * Removes component at the specified index from this menu
225 * @param index Position of the component that needs to be removed in the menu
227 public void remove(int index)
229 popupMenu.remove(index);
233 * Removes given component from this menu.
235 * @param component Component to remove
237 public void remove(Component component)
239 int index = popupMenu.getComponentIndex(component);
240 popupMenu.remove(index);
244 * Removes all menu items from the menu
246 public void removeAll()
248 popupMenu.removeAll();
252 * Creates JMenuItem with the specified text and inserts it in the
253 * at the specified index
255 * @param text label for the new menu item
256 * @param index index at which to insert newly created menu item.
258 public void insert(String text, int index)
260 this.insert(new JMenuItem(text), index);
264 * Creates JMenuItem with the specified text and inserts it in the
265 * at the specified index. IllegalArgumentException is thrown
266 * if index is less than 0
268 * @param item menu item to insert
269 * @param index index at which to insert menu item.
270 * @return Menu item that was added to the menu
272 public JMenuItem insert(JMenuItem item, int index)
274 if (index < 0)
275 throw new IllegalArgumentException("index less than zero");
277 popupMenu.insert(item, index);
279 return item;
283 * Creates JMenuItem with the associated action and inserts it to the menu
284 * at the specified index. IllegalArgumentException is thrown
285 * if index is less than 0
287 * @param action Action for the new menu item
288 * @param index index at which to insert newly created menu item.
289 * @return Menu item that was added to the menu
291 public JMenuItem insert(Action action, int index)
293 JMenuItem item = new JMenuItem(action);
294 this.insert(item, index);
296 return item;
300 * This method sets this menuItem's UI to the UIManager's default for the
301 * current look and feel.
303 public void updateUI()
305 super.setUI((MenuItemUI) UIManager.getUI(this));
306 invalidate();
310 * This method returns a name to identify which look and feel class will be
311 * the UI delegate for the menu.
313 * @return The Look and Feel classID. "MenuUI"
315 public String getUIClassID()
317 return uiClassID;
321 * Sets model for this menu.
323 * @param model model to set
325 public void setModel(ButtonModel model)
327 super.setModel(model);
331 * Returns true if the menu is selected and false otherwise
333 * @return true if the menu is selected and false otherwise
335 public boolean isSelected()
337 return super.isArmed();
341 * Changes this menu selected state if selected is true and false otherwise
342 * This method fires menuEvents to menu's registered listeners.
344 * @param selected true if the menu should be selected and false otherwise
346 public void setSelected(boolean selected)
348 // if this menu selection is true, then activate this menu and
349 // display popup associated with this menu
350 if (selected)
352 super.setArmed(true);
353 super.setSelected(true);
355 // FIXME: The popup menu should be shown on the screen after certain
356 // number of seconds pass. The 'delay' property of this menu indicates
357 // this amount of seconds. 'delay' property is 0 by default.
358 if (this.isShowing())
360 fireMenuSelected();
362 int x = 0;
363 int y = 0;
365 if (menuLocation == null)
367 // Calculate correct position of the popup. Note that location of the popup
368 // passed to show() should be relative to the popup's invoker
369 if (isTopLevelMenu())
370 y = this.getHeight();
371 else
372 x = this.getWidth();
374 getPopupMenu().show(this, x, y);
376 else
377 getPopupMenu().show(this, menuLocation.x, menuLocation.y);
381 else
383 super.setSelected(false);
384 super.setArmed(false);
385 fireMenuDeselected();
386 popupMenu.setVisible(false);
391 * Checks if PopupMenu associated with this menu is visible
393 * @return true if the popup associated with this menu is currently visible on the screen and
394 * false otherwise.
396 public boolean isPopupMenuVisible()
398 return popupMenu.isVisible();
402 * Sets popup menu visibility
404 * @param popup true if popup should be visible and false otherwise
406 public void setPopupMenuVisible(boolean popup)
408 if (getModel().isEnabled())
409 popupMenu.setVisible(popup);
413 * Returns origin point of the popup menu
415 * @return Point containing
417 protected Point getPopupMenuOrigin()
419 // if menu in the menu bar
420 if (isTopLevelMenu())
421 return new Point(0, this.getHeight());
423 // if submenu
424 return new Point(this.getWidth(), 0);
428 * Returns delay property.
430 * @return delay property, indicating number of milliseconds before
431 * popup menu associated with the menu appears or disappears after
432 * menu was selected or deselected respectively
434 public int getDelay()
436 return delay;
440 * Sets delay property for this menu. If given time for the delay
441 * property is negative, then IllegalArgumentException is thrown
443 * @param delay number of milliseconds before
444 * popup menu associated with the menu appears or disappears after
445 * menu was selected or deselected respectively
447 public void setDelay(int delay)
449 if (delay < 0)
450 throw new IllegalArgumentException("delay less than 0");
451 this.delay = delay;
455 * Sets location at which popup menu should be displayed
456 * The location given is relative to this menu item
458 * @param x x-coordinate of the menu location
459 * @param y y-coordinate of the menu location
461 public void setMenuLocation(int x, int y)
463 menuLocation = new Point(x, y);
467 * Creates and returns JMenuItem associated with the given action
469 * @param action Action to use for creation of JMenuItem
471 * @return JMenuItem that was creted with given action
473 protected JMenuItem createActionComponent(Action action)
475 return new JMenuItem(action);
479 * Creates ActionChangeListener to listen for PropertyChangeEvents occuring
480 * in the action that is associated with this menu
482 * @param item menu that contains action to listen to
484 * @return The PropertyChangeListener
486 protected PropertyChangeListener createActionChangeListener(JMenuItem item)
488 return new ActionChangedListener(item);
492 * Adds separator to the end of the menu items in the menu.
494 public void addSeparator()
496 getPopupMenu().addSeparator();
500 * Inserts separator in the menu at the specified index.
502 * @param index Index at which separator should be inserted
504 public void insertSeparator(int index)
506 if (index < 0)
507 throw new IllegalArgumentException("index less than 0");
509 getPopupMenu().insert(new JPopupMenu.Separator(), index);
513 * Returns menu item located at the specified index in the menu
515 * @param index Index at which to look for the menu item
517 * @return menu item located at the specified index in the menu
519 public JMenuItem getItem(int index)
521 if (index < 0)
522 throw new IllegalArgumentException("index less than 0");
524 Component c = popupMenu.getComponentAtIndex(index);
526 if (c instanceof JMenuItem)
527 return (JMenuItem) c;
528 else
529 return null;
533 * Returns number of items in the menu
535 * @return number of items in the menu
537 public int getItemCount()
539 // returns the number of items on
540 // the menu, including separators.
541 return getComponents().length;
545 * Checks if this menu is a tear-off menu.
547 * @return true if this menu is a tear-off menu and false otherwise
549 public boolean isTearOff()
551 // NOT YET IMPLEMENTED
552 return false;
556 * Returns number of menu components in this menu
558 * @return number of menu components in this menu
560 public int getMenuComponentCount()
562 return popupMenu.getComponentCount();
566 * Returns menu component located at the givent index
567 * in the menu
569 * @param index index at which to get the menu component in the menu
571 * @return Menu Component located in the menu at the specified index
573 public Component getMenuComponent(int index)
575 return (Component) popupMenu.getComponentAtIndex(index);
579 * Return components belonging to this menu
581 * @return components belonging to this menu
583 public Component[] getMenuComponents()
585 return popupMenu.getComponents();
589 * Checks if this menu is a top level menu. The menu is top
590 * level menu if it is inside the menu bar. While if the menu
591 * inside some other menu, it is considered to be a pull-right menu.
593 * @return true if this menu is top level menu, and false otherwise
595 public boolean isTopLevelMenu()
597 if (getParent() instanceof JMenuBar)
598 return true;
599 else
600 return false;
604 * Checks if given component exists in this menu. The submenus of
605 * this menu are checked as well
607 * @param component Component to look for
609 * @return true if the given component exists in this menu, and false otherwise
611 public boolean isMenuComponent(Component component)
613 return false;
617 * Returns popup menu associated with the menu.
619 * @return popup menu associated with the menu.
621 public JPopupMenu getPopupMenu()
623 return popupMenu;
627 * Adds MenuListener to the menu
629 * @param listener MenuListener to add
631 public void addMenuListener(MenuListener listener)
633 listenerList.add(MenuListener.class, listener);
637 * Removes MenuListener from the menu
639 * @param listener MenuListener to remove
641 public void removeMenuListener(MenuListener listener)
643 listenerList.remove(MenuListener.class, listener);
647 * This method fires MenuEvents to all menu's MenuListeners. In this case
648 * menuSelected() method of MenuListeners is called to indicated that the menu
649 * was selected.
651 protected void fireMenuSelected()
653 EventListener[] ll = listenerList.getListeners(MenuListener.class);
655 for (int i = 0; i < ll.length; i++)
656 ((MenuListener) ll[i]).menuSelected(menuEvent);
660 * This method fires MenuEvents to all menu's MenuListeners. In this case
661 * menuDeselected() method of MenuListeners is called to indicated that the menu
662 * was deselected.
664 protected void fireMenuDeselected()
666 EventListener[] ll = listenerList.getListeners(MenuListener.class);
668 for (int i = 0; i < ll.length; i++)
669 ((MenuListener) ll[i]).menuDeselected(menuEvent);
673 * This method fires MenuEvents to all menu's MenuListeners. In this case
674 * menuSelected() method of MenuListeners is called to indicated that the menu
675 * was cancelled. The menu is cancelled when it's popup menu is close without selection.
677 protected void fireMenuCanceled()
679 EventListener[] ll = listenerList.getListeners(MenuListener.class);
681 for (int i = 0; i < ll.length; i++)
682 ((MenuListener) ll[i]).menuCanceled(menuEvent);
686 * Creates WinListener that listens to the menu;s popup menu.
688 * @param popup JPopupMenu to listen to
690 * @return The WinListener
692 protected WinListener createWinListener(JPopupMenu popup)
694 return new WinListener(popup);
698 * Method of the MenuElementInterface. It reacts to the selection
699 * changes in the menu. If this menu was selected, then it
700 * displayes popup menu associated with it and if this menu was
701 * deselected it hides the popup menu.
703 * @param changed true if the menu was selected and false otherwise
705 public void menuSelectionChanged(boolean changed)
707 // if this menu selection is true, then activate this menu and
708 // display popup associated with this menu
709 setSelected(changed);
713 * Method of MenuElement interface. Returns sub components of
714 * this menu.
716 * @return array containing popupMenu that is associated with this menu
718 public MenuElement[] getSubElements()
720 return new MenuElement[] { popupMenu };
724 * @return Returns reference to itself
726 public Component getComponent()
728 return this;
732 * This method is overriden with empty implementation, s.t the
733 * accelerator couldn't be set for the menu. The mnemonic should
734 * be used for the menu instead.
736 * @param keystroke accelerator for this menu
738 public void setAccelerator(KeyStroke keystroke)
740 throw new Error("setAccelerator() is not defined for JMenu. Use setMnemonic() instead.");
744 * This method process KeyEvent occuring when the menu is visible
746 * @param event The KeyEvent
748 protected void processKeyEvent(KeyEvent event)
753 * Programatically performs click
755 * @param time Number of milliseconds for which this menu stays pressed
757 public void doClick(int time)
759 getModel().setArmed(true);
760 getModel().setPressed(true);
763 java.lang.Thread.sleep(time);
765 catch (java.lang.InterruptedException e)
767 // probably harmless
770 getModel().setPressed(false);
771 getModel().setArmed(false);
772 popupMenu.show(this, this.getWidth(), 0);
776 * A string that describes this JMenu. Normally only used
777 * for debugging.
779 * @return A string describing this JMenu
781 protected String paramString()
783 return "JMenu";
786 public AccessibleContext getAccessibleContext()
788 if (accessibleContext == null)
789 accessibleContext = new AccessibleJMenu();
791 return accessibleContext;
794 protected class AccessibleJMenu extends AccessibleJMenuItem
795 implements AccessibleSelection
797 protected AccessibleJMenu()
801 public int getAccessibleChildrenCount()
803 return 0;
806 public Accessible getAccessibleChild(int value0)
808 return null;
811 public AccessibleSelection getAccessibleSelection()
813 return null;
816 public Accessible getAccessibleSelection(int value0)
818 return null;
821 public boolean isAccessibleChildSelected(int value0)
823 return false;
826 public AccessibleRole getAccessibleRole()
828 return AccessibleRole.MENU;
831 public int getAccessibleSelectionCount()
833 return 0;
836 public void addAccessibleSelection(int value0)
840 public void removeAccessibleSelection(int value0)
844 public void clearAccessibleSelection()
848 public void selectAllAccessibleSelection()
853 protected class WinListener extends WindowAdapter implements Serializable
855 JPopupMenu popupMenu;
856 private static final long serialVersionUID = -6415815570638474823L;
858 public WinListener(JPopupMenu popup)
862 public void windowClosing(WindowEvent event)
868 * This class listens to PropertyChangeEvents occuring in menu's action
870 protected class ActionChangedListener implements PropertyChangeListener
872 /** menu item associated with the action */
873 private JMenuItem menuItem;
875 /** Creates new ActionChangedListener and adds it to menuItem's action */
876 public ActionChangedListener(JMenuItem menuItem)
878 this.menuItem = menuItem;
880 Action a = menuItem.getAction();
881 if (a != null)
882 a.addPropertyChangeListener(this);
885 /**This method is invoked when some change occures in menuItem's action*/
886 public void propertyChange(PropertyChangeEvent evt)
888 // FIXME: Need to implement