1. /*
  2. * @(#)PopupMenu.java 1.18 01/11/29
  3. *
  4. * Copyright 2002 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. /**
  10. * A class that implements a menu which can be dynamically popped up
  11. * at a specified position within a component.<p>
  12. * As the inheritance hierarchy implies, a PopupMenu can be used anywhere
  13. * a Menu can be used. However, if you use a PopupMenu like a Menu (e.g.,
  14. * you add it to a MenuBar), then you <b>cannot</b> call <code>show</code>
  15. * on that PopupMenu.
  16. *
  17. * @version 1.18 11/29/01
  18. * @author Amy Fowler
  19. */
  20. public class PopupMenu extends Menu {
  21. private static final String base = "popup";
  22. static int nameCounter = 0;
  23. /*
  24. * JDK 1.1 serialVersionUID
  25. */
  26. private static final long serialVersionUID = -4620452533522760060L;
  27. /**
  28. * Creates a new popup menu.
  29. */
  30. public PopupMenu() {
  31. this("");
  32. }
  33. /**
  34. * Creates a new popup menu with the specified name.
  35. *
  36. * @param label a non-null string specifying the popup menu's label
  37. */
  38. public PopupMenu(String label) {
  39. super(label);
  40. }
  41. /**
  42. * Construct a name for this MenuComponent. Called by getName() when
  43. * the name is null.
  44. */
  45. String constructComponentName() {
  46. synchronized (getClass()) {
  47. return base + nameCounter++;
  48. }
  49. }
  50. /**
  51. * Creates the popup menu's peer.
  52. * The peer allows us to change the appearance of the popup menu without
  53. * changing any of the popup menu's functionality.
  54. */
  55. public void addNotify() {
  56. synchronized (getTreeLock()) {
  57. // If our parent is not a Component, then this PopupMenu is
  58. // really just a plain, old Menu.
  59. if (parent != null && !(parent instanceof Component)) {
  60. super.addNotify();
  61. }
  62. else {
  63. if (peer == null)
  64. peer = Toolkit.getDefaultToolkit().createPopupMenu(this);
  65. int nitems = getItemCount();
  66. for (int i = 0 ; i < nitems ; i++) {
  67. MenuItem mi = getItem(i);
  68. mi.parent = this;
  69. mi.addNotify();
  70. }
  71. }
  72. }
  73. }
  74. /**
  75. * Shows the popup menu at the x, y position relative to an origin component.
  76. * The origin component must be contained within the component
  77. * hierarchy of the popup menu's parent. Both the origin and the parent
  78. * must be showing on the screen for this method to be valid.<p>
  79. * If this PopupMenu is being used as a Menu (i.e., it has a non-Component
  80. * parent), then you cannot call this method on the PopupMenu.
  81. *
  82. * @param origin the component which defines the coordinate space
  83. * @param x the x coordinate position to popup the menu
  84. * @param y the y coordinate position to popup the menu
  85. * @exception IllegalArgumentException if this PopupMenu has a non-
  86. * Component parent
  87. */
  88. public void show(Component origin, int x, int y) {
  89. // Use localParent for thread safety.
  90. MenuContainer localParent = parent;
  91. if (localParent == null) {
  92. throw new NullPointerException("parent is null");
  93. }
  94. if (!(localParent instanceof Component)) {
  95. throw new IllegalArgumentException(
  96. "PopupMenus with non-Component parents cannot be shown");
  97. }
  98. Component compParent = (Component)localParent;
  99. if (compParent != origin &&
  100. compParent instanceof Container &&
  101. !((Container)compParent).isAncestorOf(origin)) {
  102. throw new IllegalArgumentException(
  103. "origin not in parent's hierarchy");
  104. }
  105. if (compParent.getPeer() == null || !compParent.isShowing()) {
  106. throw new RuntimeException("parent not showing on screen");
  107. }
  108. if (peer == null) {
  109. addNotify();
  110. }
  111. synchronized (getTreeLock()) {
  112. if (peer != null) {
  113. ((PopupMenuPeer)peer).show(
  114. new Event(origin, 0, Event.MOUSE_DOWN, x, y, 0, 0));
  115. }
  116. }
  117. }
  118. }