1. /*
  2. * @(#)Popup.java 1.14 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 javax.swing;
  8. import java.awt.*;
  9. /**
  10. * Popups are used to display a <code>Component</code> to the user, typically
  11. * on top of all the other <code>Component</code>s in a particular containment
  12. * hierarchy. <code>Popup</code>s have a very small life cycle. Once you
  13. * have obtained a <code>Popup</code>, and hidden it (invoked the
  14. * <code>hide</code> method), you should no longer
  15. * invoke any methods on it. This allows the <code>PopupFactory</code> to cache
  16. * <code>Popup</code>s for later use.
  17. * <p>
  18. * The general contract is that if you need to change the size of the
  19. * <code>Component</code>, or location of the <code>Popup</code>, you should
  20. * obtain a new <code>Popup</code>.
  21. * <p>
  22. * <code>Popup</code> does not descend from <code>Component</code>, rather
  23. * implementations of <code>Popup</code> are responsible for creating
  24. * and maintaining their own <code>Component</code>s to render the
  25. * requested <code>Component</code> to the user.
  26. * <p>
  27. * You typically do not explicitly create an instance of <code>Popup</code>,
  28. * instead obtain one from a <code>PopupFactory</code>.
  29. *
  30. * @see PopupFactory
  31. *
  32. * @version 1.14 01/23/03
  33. * @since 1.4
  34. */
  35. public class Popup {
  36. /**
  37. * The Component representing the Popup.
  38. */
  39. private Component component;
  40. /**
  41. * Creates a <code>Popup</code> for the Component <code>owner</code>
  42. * containing the Component <code>contents</code>. <code>owner</code>
  43. * is used to determine which <code>Window</code> the new
  44. * <code>Popup</code> will parent the <code>Component</code> the
  45. * <code>Popup</code> creates to.
  46. * A null <code>owner</code> implies there is no valid parent.
  47. * <code>x</code> and
  48. * <code>y</code> specify the preferred initial location to place
  49. * the <code>Popup</code> at. Based on screen size, or other paramaters,
  50. * the <code>Popup</code> may not display at <code>x</code> and
  51. * <code>y</code>.
  52. *
  53. * @param owner Component mouse coordinates are relative to, may be null
  54. * @param contents Contents of the Popup
  55. * @param x Initial x screen coordinate
  56. * @param y Initial y screen coordinate
  57. * @exception IllegalArgumentException if contents is null
  58. */
  59. protected Popup(Component owner, Component contents, int x, int y) {
  60. this();
  61. if (contents == null) {
  62. throw new IllegalArgumentException("Contents must be non-null");
  63. }
  64. reset(owner, contents, x, y);
  65. }
  66. /**
  67. * Creates a <code>Popup</code>. This is provided for subclasses.
  68. */
  69. protected Popup() {
  70. }
  71. /**
  72. * Makes the <code>Popup</code> visible. If the <code>Popup</code> is
  73. * currently visible, this has no effect.
  74. */
  75. public void show() {
  76. Component component = getComponent();
  77. if (component != null) {
  78. component.show();
  79. }
  80. }
  81. /**
  82. * Hides and disposes of the <code>Popup</code>. Once a <code>Popup</code>
  83. * has been disposed you should no longer invoke methods on it. A
  84. * <code>dispose</code>d <code>Popup</code> may be reclaimed and later used
  85. * based on the <code>PopupFactory</code>. As such, if you invoke methods
  86. * on a <code>disposed</code> <code>Popup</code>, indeterminate
  87. * behavior will result.
  88. */
  89. public void hide() {
  90. Component component = getComponent();
  91. if (component instanceof JWindow) {
  92. component.hide();
  93. ((JWindow)component).getContentPane().removeAll();
  94. }
  95. dispose();
  96. }
  97. /**
  98. * Frees any resources the <code>Popup</code> may be holding onto.
  99. */
  100. void dispose() {
  101. Component component = getComponent();
  102. if (component instanceof JWindow) {
  103. ((Window)component).dispose();
  104. component = null;
  105. }
  106. }
  107. /**
  108. * Resets the <code>Popup</code> to an initial state.
  109. */
  110. void reset(Component owner, Component contents, int ownerX, int ownerY) {
  111. if (getComponent() == null) {
  112. component = createComponent(owner);
  113. }
  114. Component c = getComponent();
  115. if (c instanceof JWindow) {
  116. JWindow component = (JWindow)getComponent();
  117. component.setLocation(ownerX, ownerY);
  118. component.getContentPane().add(contents, BorderLayout.CENTER);
  119. contents.invalidate();
  120. pack();
  121. }
  122. }
  123. /**
  124. * Causes the <code>Popup</code> to be sized to fit the preferred size
  125. * of the <code>Component</code> it contains.
  126. */
  127. void pack() {
  128. Component component = getComponent();
  129. if (component instanceof Window) {
  130. ((Window)component).pack();
  131. }
  132. }
  133. /**
  134. * Returns the <code>Window</code> to use as the parent of the
  135. * <code>Window</code> created for the <code>Popup</code>. This creates
  136. * a new <code>Frame</code> each time it is invoked. Subclasses that wish
  137. * to support a different <code>Window</code> parent should override
  138. * this.
  139. */
  140. private Window getParentWindow(Component owner) {
  141. Window window = null;
  142. if (owner instanceof Window) {
  143. window = (Window)owner;
  144. }
  145. else if (owner != null) {
  146. window = SwingUtilities.getWindowAncestor(owner);
  147. }
  148. if (window == null) {
  149. window = new DefaultFrame();
  150. }
  151. return window;
  152. }
  153. /**
  154. * Creates the Component to use as the parent of the <code>Popup</code>.
  155. * The default implementation creates a <code>Window</code>, subclasses
  156. * should override.
  157. */
  158. Component createComponent(Component owner) {
  159. if (GraphicsEnvironment.isHeadless()) {
  160. // Generally not useful, bail.
  161. return null;
  162. }
  163. return new HeavyWeightWindow(getParentWindow(owner));
  164. }
  165. /**
  166. * Returns the <code>Component</code> returned from
  167. * <code>createComponent</code> that will hold the <code>Popup</code>.
  168. */
  169. Component getComponent() {
  170. return component;
  171. }
  172. /**
  173. * Component used to house window.
  174. */
  175. static class HeavyWeightWindow extends JWindow {
  176. HeavyWeightWindow(Window parent) {
  177. super(parent);
  178. setFocusableWindowState(false);
  179. setName("###overrideRedirect###");
  180. }
  181. public void update(Graphics g) {
  182. paint(g);
  183. }
  184. public void show() {
  185. super.show();
  186. this.pack();
  187. }
  188. }
  189. /**
  190. * Used if no valid Window ancestor of the supplied owner is found.
  191. * <p>
  192. * PopupFactory uses this as a way to know when the Popup shouldn't
  193. * be cached based on the Window.
  194. */
  195. static class DefaultFrame extends Frame {
  196. }
  197. }