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