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