1. /*
  2. * @(#)PopupMenu.java 1.27 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.awt;
  8. import java.awt.peer.PopupMenuPeer;
  9. import javax.accessibility.*;
  10. /**
  11. * A class that implements a menu which can be dynamically popped up
  12. * at a specified position within a component.
  13. * <p>
  14. * As the inheritance hierarchy implies, a <code>PopupMenu</code>
  15. * can be used anywhere a <code>Menu</code> can be used.
  16. * However, if you use a <code>PopupMenu</code> like a <code>Menu</code>
  17. * (e.g., you add it to a <code>MenuBar</code>), then you <b>cannot</b>
  18. * call <code>show</code> on that <code>PopupMenu</code>.
  19. *
  20. * @version 1.27 01/23/03
  21. * @author Amy Fowler
  22. */
  23. public class PopupMenu extends Menu {
  24. private static final String base = "popup";
  25. static int nameCounter = 0;
  26. /*
  27. * JDK 1.1 serialVersionUID
  28. */
  29. private static final long serialVersionUID = -4620452533522760060L;
  30. /**
  31. * Creates a new popup menu with an empty name.
  32. * @exception HeadlessException if GraphicsEnvironment.isHeadless()
  33. * returns true.
  34. * @see java.awt.GraphicsEnvironment#isHeadless
  35. */
  36. public PopupMenu() throws HeadlessException {
  37. this("");
  38. }
  39. /**
  40. * Creates a new popup menu with the specified name.
  41. *
  42. * @param label a non-<code>null</code> string specifying
  43. * the popup menu's label
  44. * @exception HeadlessException if GraphicsEnvironment.isHeadless()
  45. * returns true.
  46. * @see java.awt.GraphicsEnvironment#isHeadless
  47. */
  48. public PopupMenu(String label) throws HeadlessException {
  49. super(label);
  50. }
  51. /**
  52. * Constructs a name for this <code>MenuComponent</code>.
  53. * Called by <code>getName</code> when the name is <code>null</code>.
  54. */
  55. String constructComponentName() {
  56. synchronized (getClass()) {
  57. return base + nameCounter++;
  58. }
  59. }
  60. /**
  61. * Creates the popup menu's peer.
  62. * The peer allows us to change the appearance of the popup menu without
  63. * changing any of the popup menu's functionality.
  64. */
  65. public void addNotify() {
  66. synchronized (getTreeLock()) {
  67. // If our parent is not a Component, then this PopupMenu is
  68. // really just a plain, old Menu.
  69. if (parent != null && !(parent instanceof Component)) {
  70. super.addNotify();
  71. }
  72. else {
  73. if (peer == null)
  74. peer = Toolkit.getDefaultToolkit().createPopupMenu(this);
  75. int nitems = getItemCount();
  76. for (int i = 0 ; i < nitems ; i++) {
  77. MenuItem mi = getItem(i);
  78. mi.parent = this;
  79. mi.addNotify();
  80. }
  81. }
  82. }
  83. }
  84. /**
  85. * Shows the popup menu at the x, y position relative to an origin
  86. * component.
  87. * The origin component must be contained within the component
  88. * hierarchy of the popup menu's parent. Both the origin and the parent
  89. * must be showing on the screen for this method to be valid.
  90. * <p>
  91. * If this <code>PopupMenu</code> is being used as a <code>Menu</code>
  92. * (i.e., it has a non-<code>Component</code> parent),
  93. * then you cannot call this method on the <code>PopupMenu</code>.
  94. *
  95. * @param origin the component which defines the coordinate space
  96. * @param x the x coordinate position to popup the menu
  97. * @param y the y coordinate position to popup the menu
  98. * @exception NullPointerException if the parent is <code>null</code>
  99. * @exception IllegalArgumentException if this <code>PopupMenu</code>
  100. * has a non-<code>Component</code> parent
  101. * @exception IllegalArgumentException if the origin is not in the
  102. * parent's heirarchy
  103. * @exception RuntimeException if the parent is not showing on screen
  104. */
  105. public void show(Component origin, int x, int y) {
  106. // Use localParent for thread safety.
  107. MenuContainer localParent = parent;
  108. if (localParent == null) {
  109. throw new NullPointerException("parent is null");
  110. }
  111. if (!(localParent instanceof Component)) {
  112. throw new IllegalArgumentException(
  113. "PopupMenus with non-Component parents cannot be shown");
  114. }
  115. Component compParent = (Component)localParent;
  116. if (compParent != origin &&
  117. compParent instanceof Container &&
  118. !((Container)compParent).isAncestorOf(origin)) {
  119. throw new IllegalArgumentException(
  120. "origin not in parent's hierarchy");
  121. }
  122. if (compParent.getPeer() == null || !compParent.isShowing()) {
  123. throw new RuntimeException("parent not showing on screen");
  124. }
  125. if (peer == null) {
  126. addNotify();
  127. }
  128. synchronized (getTreeLock()) {
  129. if (peer != null) {
  130. ((PopupMenuPeer)peer).show(
  131. new Event(origin, 0, Event.MOUSE_DOWN, x, y, 0, 0));
  132. }
  133. }
  134. }
  135. /////////////////
  136. // Accessibility support
  137. ////////////////
  138. /**
  139. * Gets the <code>AccessibleContext</code> associated with this
  140. * <code>PopupMenu</code>.
  141. *
  142. * @return the <code>AccessibleContext</code> of this
  143. * <code>PopupMenu</code>
  144. */
  145. public AccessibleContext getAccessibleContext() {
  146. if (accessibleContext == null) {
  147. accessibleContext = new AccessibleAWTPopupMenu();
  148. }
  149. return accessibleContext;
  150. }
  151. /**
  152. * Inner class of PopupMenu used to provide default support for
  153. * accessibility. This class is not meant to be used directly by
  154. * application developers, but is instead meant only to be
  155. * subclassed by menu component developers.
  156. * <p>
  157. * The class used to obtain the accessible role for this object.
  158. */
  159. protected class AccessibleAWTPopupMenu extends AccessibleAWTMenu {
  160. /**
  161. * Get the role of this object.
  162. *
  163. * @return an instance of AccessibleRole describing the role of the
  164. * object
  165. */
  166. public AccessibleRole getAccessibleRole() {
  167. return AccessibleRole.POPUP_MENU;
  168. }
  169. } // class AccessibleAWTPopupMenu
  170. }