1. /*
  2. * @(#)DefaultPopupFactory.java 1.12 01/02/20
  3. *
  4. * Copyright 1997-2001 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 javax.swing;
  11. import java.applet.Applet;
  12. import java.awt.*;
  13. import java.awt.event.*;
  14. import javax.accessibility.*;
  15. import java.io.Serializable;
  16. import java.util.Hashtable;
  17. import java.util.Locale;
  18. import java.util.Vector;
  19. class DefaultPopupFactory implements PopupFactory {
  20. private transient Component component;
  21. protected transient Component invoker;
  22. private transient Popup popup;
  23. private transient Frame frame;
  24. private int desiredLocationX,desiredLocationY;
  25. private int lastPopupType = LIGHT_WEIGHT_POPUP;
  26. private static final Object heavyPopupCacheKey =
  27. new StringBuffer("PopupFactory.heavyPopupCache");
  28. private static final Object lightPopupCacheKey =
  29. new StringBuffer("PopupFactory.lightPopupCache");
  30. private static final Object mediumPopupCacheKey =
  31. new StringBuffer("PopupFactory.mediumPopupCache");
  32. private static final Object defaultLWPopupEnabledKey =
  33. new StringBuffer("PopupFactory.defaultLWPopupEnabledKey");
  34. private static final int MAX_CACHE_SIZE = 5;
  35. private boolean lightWeightPopupEnabled = true;
  36. /** A light weight popup is used when it fits and light weight popups are enabled **/
  37. private static final int LIGHT_WEIGHT_POPUP = 0;
  38. /** A "Medium weight" popup is a panel. We use this when downgrading an heavy weight in
  39. * dialogs
  40. */
  41. private static final int MEDIUM_WEIGHT_POPUP = 1;
  42. /** A popup implemented with a window */
  43. private static final int HEAVY_WEIGHT_POPUP = 2;
  44. /* Lock object used in place of class object for synchronization.
  45. * (4187686)
  46. */
  47. private static final Object classLock = new Object();
  48. /**
  49. * Set the default value for the <b>lightWeightPopupEnabled</b>
  50. * property.
  51. */
  52. /* Pending(arnaud) this property should scope to awt-context */
  53. public static void setDefaultLightWeightPopupEnabled(boolean aFlag) {
  54. SwingUtilities.appContextPut(defaultLWPopupEnabledKey,
  55. new Boolean(aFlag));
  56. }
  57. /**
  58. * Return the default value for the <b>lightWeightPopupEnabled</b>
  59. * property.
  60. */
  61. public static boolean getDefaultLightWeightPopupEnabled() {
  62. Boolean b = (Boolean)
  63. SwingUtilities.appContextGet(defaultLWPopupEnabledKey);
  64. if (b == null) {
  65. SwingUtilities.appContextPut(defaultLWPopupEnabledKey,
  66. Boolean.TRUE);
  67. return true;
  68. }
  69. return b.booleanValue();
  70. }
  71. public void setLightWeightPopupEnabled(boolean aFlag) {
  72. // PENDING(ges): should be bound
  73. lightWeightPopupEnabled = aFlag;
  74. }
  75. public boolean isLightWeightPopupEnabled() {
  76. return lightWeightPopupEnabled;
  77. }
  78. private static Hashtable getHeavyPopupCache() {
  79. Hashtable cache =
  80. (Hashtable)SwingUtilities.appContextGet(heavyPopupCacheKey);
  81. if (cache == null) {
  82. cache = new Hashtable(2);
  83. SwingUtilities.appContextPut(heavyPopupCacheKey, cache);
  84. }
  85. return cache;
  86. }
  87. private static Vector getLightPopupCache() {
  88. Vector cache =
  89. (Vector)SwingUtilities.appContextGet(lightPopupCacheKey);
  90. if (cache == null) {
  91. cache = new Vector();
  92. SwingUtilities.appContextPut(lightPopupCacheKey, cache);
  93. }
  94. return cache;
  95. }
  96. private static Vector getMediumPopupCache() {
  97. Vector cache =
  98. (Vector)SwingUtilities.appContextGet(mediumPopupCacheKey);
  99. if (cache == null) {
  100. cache = new Vector();
  101. SwingUtilities.appContextPut(mediumPopupCacheKey, cache);
  102. }
  103. return cache;
  104. }
  105. static void recycleHeavyPopup(Popup aPopup) {
  106. synchronized (classLock) {
  107. Vector cache;
  108. final Window w = SwingUtilities.getWindowAncestor((Component)aPopup);
  109. Hashtable heavyPopupCache = getHeavyPopupCache();
  110. if (heavyPopupCache.containsKey(w)) {
  111. cache = (Vector)heavyPopupCache.get(w);
  112. } else {
  113. cache = new Vector();
  114. heavyPopupCache.put(w, cache);
  115. // Clean up if the Window is closed
  116. w.addWindowListener(new WindowAdapter() {
  117. public void windowClosed(WindowEvent e) {
  118. Hashtable heavyPopupCache2 = getHeavyPopupCache();
  119. heavyPopupCache2.remove(w);
  120. }
  121. });
  122. }
  123. if(cache.size() < MAX_CACHE_SIZE) {
  124. cache.addElement(aPopup);
  125. }
  126. }
  127. }
  128. static Popup getRecycledHeavyPopup(Window w) {
  129. synchronized (classLock) {
  130. Vector cache;
  131. Hashtable heavyPopupCache = getHeavyPopupCache();
  132. if (heavyPopupCache.containsKey(w)) {
  133. cache = (Vector)heavyPopupCache.get(w);
  134. } else {
  135. return null;
  136. }
  137. int c;
  138. if((c=cache.size()) > 0) {
  139. Popup r = (Popup)cache.elementAt(0);
  140. cache.removeElementAt(0);
  141. return r;
  142. }
  143. return null;
  144. }
  145. }
  146. static void recycleLightPopup(Popup aPopup) {
  147. synchronized (classLock) {
  148. Vector lightPopupCache = getLightPopupCache();
  149. if (lightPopupCache.size() < MAX_CACHE_SIZE) {
  150. lightPopupCache.addElement(aPopup);
  151. }
  152. }
  153. }
  154. static Popup getRecycledLightPopup() {
  155. synchronized (classLock) {
  156. Vector lightPopupCache = getLightPopupCache();
  157. int c;
  158. if((c=lightPopupCache.size()) > 0) {
  159. Popup r = (Popup)lightPopupCache.elementAt(0);
  160. lightPopupCache.removeElementAt(0);
  161. return r;
  162. }
  163. return null;
  164. }
  165. }
  166. static void recycleMediumPopup(Popup aPopup) {
  167. synchronized (classLock) {
  168. Vector mediumPopupCache = getMediumPopupCache();
  169. if(mediumPopupCache.size() < MAX_CACHE_SIZE) {
  170. mediumPopupCache.addElement(aPopup);
  171. }
  172. }
  173. }
  174. static Popup getRecycledMediumPopup() {
  175. synchronized (classLock) {
  176. Vector mediumPopupCache = getMediumPopupCache();
  177. int c;
  178. if((c=mediumPopupCache.size()) > 0) {
  179. Popup r = (Popup)mediumPopupCache.elementAt(0);
  180. mediumPopupCache.removeElementAt(0);
  181. return r;
  182. }
  183. return null;
  184. }
  185. }
  186. static void recyclePopup(Popup aPopup) {
  187. if(aPopup instanceof JPanelPopup)
  188. recycleLightPopup(aPopup);
  189. else if(aPopup instanceof WindowPopup)
  190. recycleHeavyPopup(aPopup);
  191. else if(aPopup instanceof PanelPopup)
  192. recycleMediumPopup(aPopup);
  193. }
  194. protected Popup createLightWeightPopup() {
  195. Popup popup;
  196. popup = DefaultPopupFactory.getRecycledLightPopup();
  197. if(popup == null) {
  198. popup = new JPanelPopup();
  199. }
  200. return popup;
  201. }
  202. protected Popup createMediumWeightPopup() {
  203. Popup popup;
  204. popup = DefaultPopupFactory.getRecycledMediumPopup();
  205. if(popup == null) {
  206. popup = new PanelPopup();
  207. }
  208. return popup;
  209. }
  210. protected Popup createHeavyWeightPopup() {
  211. Window window = invoker != null? SwingUtilities.getWindowAncestor(invoker) : null;
  212. if (window != null) {
  213. popup = DefaultPopupFactory.getRecycledHeavyPopup(window);
  214. } else {
  215. window = new Frame();
  216. }
  217. if (popup == null) {
  218. popup = new WindowPopup(window);
  219. }
  220. /* Fix Forte Menu Bug. awt_TopLevel.c looks for Window name
  221. * "###overrideRedirect###" to determine that XmNoverrideRedirect
  222. * needs to be set.
  223. */
  224. ((Window)popup).setName("###overrideRedirect###");
  225. return popup;
  226. }
  227. private boolean popupFit(Rectangle popupRectInScreen) {
  228. if(invoker != null) {
  229. Container parent;
  230. for(parent = invoker.getParent(); parent != null ; parent = parent.getParent()) {
  231. if(parent instanceof JFrame || parent instanceof JDialog ||
  232. parent instanceof JWindow) {
  233. return SwingUtilities.isRectangleContainingRectangle(parent.getBounds(),popupRectInScreen);
  234. } else if(parent instanceof JApplet) {
  235. Rectangle r = parent.getBounds();
  236. Point p = parent.getLocationOnScreen();
  237. r.x = p.x;
  238. r.y = p.y;
  239. return SwingUtilities.isRectangleContainingRectangle(r,popupRectInScreen);
  240. } else if(parent instanceof java.awt.Frame) {
  241. return SwingUtilities.isRectangleContainingRectangle(parent.getBounds(),popupRectInScreen);
  242. }
  243. }
  244. }
  245. return false;
  246. }
  247. private boolean ancestorIsModalDialog(Component i) {
  248. Container parent = null;
  249. if (i !=null) {
  250. for(parent = i.getParent() ; parent != null ; parent = parent.getParent())
  251. if ((parent instanceof Dialog) && (((Dialog)parent).isModal() == true))
  252. return true;
  253. }
  254. return false;
  255. }
  256. private void replacePopup(int newType) {
  257. popup.removeComponent(component);
  258. recyclePopup(popup);
  259. popup = null;
  260. switch(newType) {
  261. case LIGHT_WEIGHT_POPUP:
  262. popup = createLightWeightPopup();
  263. break;
  264. case MEDIUM_WEIGHT_POPUP:
  265. popup = createMediumWeightPopup();
  266. break;
  267. case HEAVY_WEIGHT_POPUP:
  268. popup = createHeavyWeightPopup();
  269. break;
  270. }
  271. popup.setLocationOnScreen(desiredLocationX,desiredLocationY);
  272. /*
  273. System.out.println("Adding " + component.hashCode() + "::" +
  274. component + " to " + popup.hashCode() + "::"
  275. + popup);
  276. */
  277. popup.addComponent(component,"Center");
  278. component.invalidate();
  279. // popup.setBackground(component.getBackground());
  280. popup.pack();
  281. }
  282. private boolean invokerInHeavyWeightPopup(Component i) {
  283. if (i !=null) {
  284. Container parent;
  285. for(parent = i.getParent() ; parent != null ; parent =
  286. parent.getParent()) {
  287. if(parent instanceof WindowPopup)
  288. return true;
  289. else if(parent instanceof PanelPopup)
  290. break;
  291. else if(parent instanceof JPanelPopup)
  292. break;
  293. }
  294. }
  295. return false;
  296. }
  297. public Popup getPopup(Component comp, Component invoker, int x, int y) {
  298. this.invoker = invoker;
  299. this.component = comp;
  300. this.desiredLocationX = x;
  301. this.desiredLocationY = y;
  302. int popupType;
  303. int newPopupType;
  304. switch(lastPopupType) {
  305. case LIGHT_WEIGHT_POPUP:
  306. popup = createLightWeightPopup();
  307. break;
  308. case MEDIUM_WEIGHT_POPUP:
  309. popup = createMediumWeightPopup();
  310. break;
  311. case HEAVY_WEIGHT_POPUP:
  312. popup = createHeavyWeightPopup();
  313. break;
  314. }
  315. popupType = lastPopupType;
  316. popup.setLocationOnScreen(desiredLocationX,desiredLocationY);
  317. popup.addComponent(component,"Center");
  318. // popup.setBackground(component.getBackground());
  319. popup.pack();
  320. /*
  321. System.out.println("Adding " + component.hashCode() + "::" +
  322. component + " to " + popup.hashCode() + "::"
  323. + popup);
  324. */
  325. Rectangle popupRect = new Rectangle(desiredLocationX,desiredLocationY,
  326. popup.getWidth(),popup.getHeight());
  327. if(popupFit(popupRect)) {
  328. if(((comp instanceof JToolTip) ||
  329. (comp instanceof JPopupMenu &&
  330. ((JPopupMenu)comp).isLightWeightPopupEnabled()))
  331. && lightWeightPopupEnabled) {
  332. newPopupType = LIGHT_WEIGHT_POPUP;
  333. } else {
  334. newPopupType = MEDIUM_WEIGHT_POPUP;
  335. }
  336. } else {
  337. newPopupType = HEAVY_WEIGHT_POPUP;
  338. }
  339. if(invokerInHeavyWeightPopup(invoker)) {
  340. newPopupType = HEAVY_WEIGHT_POPUP;
  341. }
  342. if(invoker == null) {
  343. newPopupType = HEAVY_WEIGHT_POPUP;
  344. }
  345. if(newPopupType != popupType) {
  346. replacePopup(newPopupType);
  347. popupType = newPopupType;
  348. }
  349. lastPopupType = popupType;
  350. return popup;
  351. }
  352. /**
  353. * A class used to popup a window.
  354. * <p>
  355. * <strong>Warning:</strong>
  356. * Serialized objects of this class will not be compatible with
  357. * future Swing releases. The current serialization support is appropriate
  358. * for short term storage or RMI between applications running the same
  359. * version of Swing. A future release of Swing will provide support for
  360. * long term persistence.
  361. */
  362. protected class WindowPopup extends JWindow implements Popup,Serializable,Accessible {
  363. int saveX,saveY;
  364. boolean firstShow = true;
  365. public WindowPopup(Window w) {
  366. super(w);
  367. }
  368. public Component getComponent() {
  369. return this;
  370. }
  371. public int getWidth() {
  372. return getBounds().width;
  373. }
  374. public int getHeight() {
  375. return getBounds().height;
  376. }
  377. public void update(Graphics g) {
  378. paint(g);
  379. }
  380. public void show(Component invoker) {
  381. this.setLocation(saveX,saveY);
  382. this.setVisible(true);
  383. /** This hack is to workaround a bug on Solaris where the windows does not really show
  384. * the first time
  385. */
  386. if(firstShow) {
  387. this.hide();
  388. this.setVisible(true);
  389. firstShow = false;
  390. }
  391. }
  392. public void hide() {
  393. super.hide();
  394. /** We need to call removeNotify() here because hide() does something only if
  395. * Component.visible is true. When the app frame is miniaturized, the parent
  396. * frame of this frame is invisible, causing AWT to believe that this frame
  397. * is invisible and causing hide() to do nothing
  398. */
  399. removeNotify();
  400. }
  401. public Rectangle getBoundsOnScreen() {
  402. return getBounds();
  403. }
  404. public void setLocationOnScreen(int x,int y) {
  405. this.setLocation(x,y);
  406. saveX = x;
  407. saveY = y;
  408. }
  409. public void addComponent(Component aComponent,Object constraints) {
  410. this.getContentPane().add(aComponent,constraints);
  411. }
  412. public void removeComponent(Component c) {
  413. this.getContentPane().remove(c);
  414. recyclePopup(this);
  415. }
  416. /**
  417. * Get the AccessibleContext associated with this popup
  418. *
  419. * @return the AccessibleContext of this popup
  420. */
  421. public AccessibleContext getAccessibleContext() {
  422. if (accessibleContext == null) {
  423. accessibleContext = new AccessibleWindowPopup();
  424. }
  425. return accessibleContext;
  426. }
  427. /**
  428. * The class used to obtain the accessible role for this object.
  429. * <p>
  430. * <strong>Warning:</strong>
  431. * Serialized objects of this class will not be compatible with
  432. * future Swing releases. The current serialization support is appropriate
  433. * for short term storage or RMI between applications running the same
  434. * version of Swing. A future release of Swing will provide support for
  435. * long term persistence.
  436. */
  437. protected class AccessibleWindowPopup extends AccessibleContext
  438. implements Serializable, AccessibleComponent {
  439. protected AccessibleContext accessibleContext = null;
  440. // AccessibleContext methods
  441. //
  442. /**
  443. * Get the role of this object.
  444. *
  445. * @return an instance of AccessibleRole describing the role of
  446. * the object
  447. * @see AccessibleRole
  448. */
  449. public AccessibleRole getAccessibleRole() {
  450. return AccessibleRole.WINDOW;
  451. }
  452. /**
  453. * Get the state of this object.
  454. *
  455. * @return an instance of AccessibleStateSet containing the
  456. * current state set of the object
  457. * @see AccessibleState
  458. */
  459. public AccessibleStateSet getAccessibleStateSet() {
  460. AccessibleStateSet states = new AccessibleStateSet();
  461. if (getFocusOwner() != null) {
  462. states.add(AccessibleState.ACTIVE);
  463. states.add(AccessibleState.FOCUSED);
  464. }
  465. if (isFocusTraversable()) {
  466. states.add(AccessibleState.FOCUSABLE);
  467. }
  468. if (isOpaque()) {
  469. states.add(AccessibleState.OPAQUE);
  470. }
  471. if (isShowing()) {
  472. states.add(AccessibleState.SHOWING);
  473. }
  474. if (isVisible()) {
  475. states.add(AccessibleState.VISIBLE);
  476. }
  477. return states;
  478. }
  479. /**
  480. * Get the Accessible parent of this object. If the parent of this
  481. * object implements Accessible, this method should simply return
  482. * getParent().
  483. *
  484. * @return the Accessible parent of this object -- can be null if
  485. * this object does not have an Accessible parent
  486. */
  487. public Accessible getAccessibleParent() {
  488. if (accessibleParent != null) {
  489. return accessibleParent;
  490. } else {
  491. Container parent = getParent();
  492. if (parent instanceof Accessible) {
  493. return (Accessible) parent;
  494. }
  495. }
  496. return null;
  497. }
  498. /**
  499. * Get the index of this object in its accessible parent.
  500. *
  501. * @return the index of this object in its parent; -1 if this
  502. * object does not have an accessible parent.
  503. * @see #getAccessibleParent
  504. */
  505. public int getAccessibleIndexInParent() {
  506. return SwingUtilities.getAccessibleIndexInParent(WindowPopup.this);
  507. }
  508. /**
  509. * Returns the number of accessible children in the object. If all
  510. * of the children of this object implement Accessible, than this
  511. * method should return the number of children of this object.
  512. *
  513. * @return the number of accessible children in the object.
  514. */
  515. public int getAccessibleChildrenCount() {
  516. return SwingUtilities.getAccessibleChildrenCount(WindowPopup.this);
  517. }
  518. /**
  519. * Return the nth Accessible child of the object.
  520. *
  521. * @param i zero-based index of child
  522. * @return the nth Accessible child of the object
  523. */
  524. public Accessible getAccessibleChild(int i) {
  525. return SwingUtilities.getAccessibleChild(WindowPopup.this,i);
  526. }
  527. /**
  528. * Return the locale of this object.
  529. *
  530. * @return the locale of this object
  531. */
  532. public Locale getLocale() {
  533. return WindowPopup.this.getLocale();
  534. }
  535. /**
  536. * Get the AccessibleComponent associated with this object if one
  537. * exists. Otherwise return null.
  538. */
  539. public AccessibleComponent getAccessibleComponent() {
  540. return this;
  541. }
  542. // AccessibleComponent methods
  543. //
  544. /**
  545. * Get the background color of this object.
  546. *
  547. * @return the background color, if supported, of the object;
  548. * otherwise, null
  549. */
  550. public Color getBackground() {
  551. return WindowPopup.this.getBackground();
  552. }
  553. /**
  554. * Set the background color of this object.
  555. *
  556. * @param c the new Color for the background
  557. */
  558. public void setBackground(Color c) {
  559. WindowPopup.this.setBackground(c);
  560. }
  561. /**
  562. * Get the foreground color of this object.
  563. *
  564. * @return the foreground color, if supported, of the object;
  565. * otherwise, null
  566. */
  567. public Color getForeground() {
  568. return WindowPopup.this.getForeground();
  569. }
  570. /**
  571. * Set the foreground color of this object.
  572. *
  573. * @param c the new Color for the foreground
  574. */
  575. public void setForeground(Color c) {
  576. WindowPopup.this.setForeground(c);
  577. }
  578. /**
  579. * Get the Cursor of this object.
  580. *
  581. * @return the Cursor, if supported, of the object; otherwise, null
  582. */
  583. public Cursor getCursor() {
  584. return WindowPopup.this.getCursor();
  585. }
  586. /**
  587. * Set the Cursor of this object.
  588. *
  589. * @param c the new Cursor for the object
  590. */
  591. public void setCursor(Cursor cursor) {
  592. WindowPopup.this.setCursor(cursor);
  593. }
  594. /**
  595. * Get the Font of this object.
  596. *
  597. * @return the Font,if supported, for the object; otherwise, null
  598. */
  599. public Font getFont() {
  600. return WindowPopup.this.getFont();
  601. }
  602. /**
  603. * Set the Font of this object.
  604. *
  605. * @param f the new Font for the object
  606. */
  607. public void setFont(Font f) {
  608. WindowPopup.this.setFont(f);
  609. }
  610. /**
  611. * Get the FontMetrics of this object.
  612. *
  613. * @param f the Font
  614. * @return the FontMetrics, if supported, the object;
  615. * otherwise, null
  616. * @see #getFont
  617. */
  618. public FontMetrics getFontMetrics(Font f) {
  619. return WindowPopup.this.getFontMetrics(f);
  620. }
  621. /**
  622. * Determine if the object is enabled.
  623. *
  624. * @return true if object is enabled; otherwise, false
  625. */
  626. public boolean isEnabled() {
  627. return WindowPopup.this.isEnabled();
  628. }
  629. /**
  630. * Set the enabled state of the object.
  631. *
  632. * @param b if true, enables this object; otherwise, disables it
  633. */
  634. public void setEnabled(boolean b) {
  635. WindowPopup.this.setEnabled(b);
  636. }
  637. /**
  638. * Determine if the object is visible. Note: this means that the
  639. * object intends to be visible; however, it may not in fact be
  640. * showing on the screen because one of the objects this object
  641. * is contained by is not visible. To determine if an object is
  642. * showing on the screen, use isShowing().
  643. *
  644. * @return true if object is visible; otherwise, false
  645. */
  646. public boolean isVisible() {
  647. return WindowPopup.this.isVisible();
  648. }
  649. /**
  650. * Set the visible state of the object.
  651. *
  652. * @param b if true, shows this object; otherwise, hides it
  653. */
  654. public void setVisible(boolean b) {
  655. WindowPopup.this.setVisible(b);
  656. }
  657. /**
  658. * Determine if the object is showing. Determined by checking
  659. * the visibility of the object and ancestors of the object.
  660. * This will return true even if the object is obscured by another
  661. * (for example, it is underneath a menu that was pulled
  662. * down).
  663. *
  664. * @return true if object is showing; otherwise, false
  665. */
  666. public boolean isShowing() {
  667. return WindowPopup.this.isShowing();
  668. }
  669. /**
  670. * Checks if the specified point is within this object's bounds,
  671. * where the point's x and y coordinates are defined to be relative
  672. * to the coordinate system of the object.
  673. *
  674. * @param p the Point relative to the coordinate system of the
  675. * object
  676. * @return true if object contains Point; otherwise false
  677. */
  678. public boolean contains(Point p) {
  679. return WindowPopup.this.contains(p);
  680. }
  681. /**
  682. * Returns the location of the object on the screen.
  683. *
  684. * @return location of object on screen -- can be null if this
  685. * object is not on the screen
  686. */
  687. public Point getLocationOnScreen() {
  688. return WindowPopup.this.getLocationOnScreen();
  689. }
  690. /**
  691. * Gets the location of the object relative to the parent in the
  692. * form of a point specifying the object's top-left corner in the
  693. * screen's coordinate space.
  694. *
  695. * @return An instance of Point representing the top-left corner
  696. * of the objects's bounds in the coordinate space of the screen;
  697. * null if this object or its parent are not on the screen
  698. */
  699. public Point getLocation() {
  700. return WindowPopup.this.getLocation();
  701. }
  702. /**
  703. * Sets the location of the object relative to the parent.
  704. */
  705. public void setLocation(Point p) {
  706. WindowPopup.this.setLocation(p);
  707. }
  708. /**
  709. * Gets the bounds of this object in the form of a Rectangle
  710. * object. The bounds specify this object's width, height,
  711. * and location relative to its parent.
  712. *
  713. * @return A rectangle indicating this component's bounds; null if
  714. * this object is not on the screen.
  715. */
  716. public Rectangle getBounds() {
  717. return WindowPopup.this.getBounds();
  718. }
  719. /**
  720. * Sets the bounds of this object in the form of a Rectangle
  721. * object. The bounds specify this object's width, height,
  722. * and location relative to its parent.
  723. *
  724. * @param A rectangle indicating this component's bounds
  725. */
  726. public void setBounds(Rectangle r) {
  727. WindowPopup.this.setBounds(r);
  728. }
  729. /**
  730. * Returns the size of this object in the form of a Dimension
  731. * object. The height field of the Dimension object contains
  732. * this objects's height, and the width field of the Dimension
  733. * object contains this object's width.
  734. *
  735. * @return A Dimension object that indicates the size of this
  736. * component; null if this object is not on the screen
  737. */
  738. public Dimension getSize() {
  739. return WindowPopup.this.getSize();
  740. }
  741. /**
  742. * Resizes this object so that it has width width and height.
  743. *
  744. * @param d - The dimension specifying the new size of the object.
  745. */
  746. public void setSize(Dimension d) {
  747. WindowPopup.this.setSize(d);
  748. }
  749. /**
  750. * Returns the Accessible child, if one exists, contained at the
  751. * local coordinate Point.
  752. *
  753. * @param p The point defining the top-left corner of the
  754. * Accessible, given in the coordinate space of the object's
  755. * parent.
  756. * @return the Accessible, if it exists, at the specified
  757. * location; else null
  758. */
  759. public Accessible getAccessibleAt(Point p) {
  760. return SwingUtilities.getAccessibleAt(WindowPopup.this,p);
  761. }
  762. /**
  763. * Returns whether this object can accept focus or not.
  764. *
  765. * @return true if object can accept focus; otherwise false
  766. */
  767. public boolean isFocusTraversable() {
  768. return WindowPopup.this.isFocusTraversable();
  769. }
  770. /**
  771. * Requests focus for this object.
  772. */
  773. public void requestFocus() {
  774. WindowPopup.this.requestFocus();
  775. }
  776. /**
  777. * Adds the specified focus listener to receive focus events from
  778. * this component.
  779. *
  780. * @param l the focus listener
  781. */
  782. public void addFocusListener(FocusListener l) {
  783. WindowPopup.this.addFocusListener(l);
  784. }
  785. /**
  786. * Removes the specified focus listener so it no longer receives
  787. * focus events from this component.
  788. *
  789. * @param l the focus listener
  790. */
  791. public void removeFocusListener(FocusListener l) {
  792. WindowPopup.this.removeFocusListener(l);
  793. }
  794. } // inner class AccessibleWindowPopup
  795. }
  796. /**
  797. * A class used to popup a JPanel.
  798. * <p>
  799. * <strong>Warning:</strong>
  800. * Serialized objects of this class will not be compatible with
  801. * future Swing releases. The current serialization support is appropriate
  802. * for short term storage or RMI between applications running the same
  803. * version of Swing. A future release of Swing will provide support for
  804. * long term persistence.
  805. */
  806. protected class JPanelPopup extends JPanel implements Popup,Serializable {
  807. int desiredLocationX,desiredLocationY;
  808. public JPanelPopup() {
  809. super();
  810. setLayout(new BorderLayout());
  811. setDoubleBuffered(true);
  812. this.setOpaque(true);
  813. }
  814. public Component getComponent() {
  815. return this;
  816. }
  817. public void addComponent(Component aComponent,Object constraints) {
  818. this.add(aComponent,constraints);
  819. }
  820. public void removeComponent(Component c) {
  821. this.remove(c);
  822. }
  823. public void update(Graphics g) {
  824. paint(g);
  825. }
  826. public void pack() {
  827. setSize(getPreferredSize());
  828. }
  829. public void show(Component invoker) {
  830. Container parent = null;
  831. if (invoker != null)
  832. parent = invoker.getParent();
  833. Window parentWindow = null;
  834. for(Container p = parent; p != null; p = p.getParent()) {
  835. if(p instanceof JRootPane) {
  836. if(p.getParent() instanceof JInternalFrame)
  837. continue;
  838. parent = ((JRootPane)p).getLayeredPane();
  839. for(p = parent.getParent(); p != null && (!(p instanceof java.awt.Window));
  840. p = p.getParent());
  841. parentWindow = (Window)p;
  842. break;
  843. } else if(p instanceof Window) {
  844. parent = p;
  845. parentWindow = (Window)p;
  846. break;
  847. }
  848. }
  849. Point p = convertScreenLocationToParent(parent,desiredLocationX,desiredLocationY);
  850. this.setLocation(p.x,p.y);
  851. if(parent instanceof JLayeredPane) {
  852. ((JLayeredPane)parent).add(this,JLayeredPane.POPUP_LAYER,0);
  853. } else
  854. parent.add(this);
  855. }
  856. public void hide() {
  857. Container parent = getParent();
  858. Rectangle r = this.getBounds();
  859. if(parent != null)
  860. parent.remove(this);
  861. parent.repaint(r.x,r.y,r.width,r.height);
  862. }
  863. public Rectangle getBoundsOnScreen() {
  864. Container parent = getParent();
  865. if(parent != null) {
  866. Rectangle r = getBounds();
  867. Point p;
  868. p = convertParentLocationToScreen(parent,r.x,r.y);
  869. r.x = p.x;
  870. r.y = p.y;
  871. return r;
  872. } else
  873. throw new Error("getBoundsOnScreen called on an invisible popup");
  874. }
  875. Point convertParentLocationToScreen(Container parent,int x,int y) {
  876. Window parentWindow = null;
  877. Rectangle r;
  878. Container p;
  879. Point pt;
  880. for(p = this; p != null; p = p.getParent()) {
  881. if(p instanceof Window) {
  882. parentWindow = (Window)p;
  883. break;
  884. }
  885. }
  886. if(parentWindow != null) {
  887. r = parentWindow.getBounds();
  888. pt = new Point(x,y);
  889. pt = SwingUtilities.convertPoint(parent,pt,null);
  890. pt.x += r.x;
  891. pt.y += r.y;
  892. return pt;
  893. } else
  894. throw new Error("convertParentLocationToScreen: no window ancestor found"); }
  895. Point convertScreenLocationToParent(Container parent,int x,int y) {
  896. Window parentWindow = null;
  897. Rectangle r;
  898. for(Container p = parent; p != null; p = p.getParent()) {
  899. if(p instanceof Window) {
  900. parentWindow = (Window)p;
  901. break;
  902. }
  903. }
  904. if(parentWindow != null) {
  905. Point p = new Point(x,y);
  906. SwingUtilities.convertPointFromScreen(p,parent);
  907. return p;
  908. } else
  909. throw new Error("convertScreenLocationToParent: no window ancestor found");
  910. }
  911. public void setLocationOnScreen(int x,int y) {
  912. Container parent = getParent();
  913. if(parent != null) {
  914. Point p = convertScreenLocationToParent(parent,x,y);
  915. this.setLocation(p.x,p.y);
  916. } else {
  917. desiredLocationX = x;
  918. desiredLocationY = y;
  919. }
  920. }
  921. }
  922. /**
  923. * A class used to popup an AWT panel.
  924. * <p>
  925. * <strong>Warning:</strong>
  926. * Serialized objects of this class will not be compatible with
  927. * future Swing releases. The current serialization support is appropriate
  928. * for short term storage or RMI between applications running the same
  929. * version of Swing. A future release of Swing will provide support for
  930. * long term persistence.
  931. */
  932. protected class PanelPopup extends Panel implements Popup,Serializable {
  933. int desiredLocationX,desiredLocationY;
  934. JRootPane rootPane;
  935. public PanelPopup() {
  936. super();
  937. setLayout(new BorderLayout());
  938. rootPane = new JRootPane();
  939. this.add(rootPane, BorderLayout.CENTER);
  940. }
  941. public int getWidth() {
  942. return getBounds().width;
  943. }
  944. public int getHeight() {
  945. return getBounds().height;
  946. }
  947. public Component getComponent() {
  948. return this;
  949. }
  950. public void addComponent(Component aComponent,Object constraints) {
  951. rootPane.getContentPane().add(aComponent,constraints);
  952. }
  953. public void removeComponent(Component c) {
  954. rootPane.getContentPane().remove(c);
  955. }
  956. public void update(Graphics g) {
  957. paint(g);
  958. }
  959. public void paint(Graphics g) {
  960. super.paint(g);
  961. }
  962. public void pack() {
  963. setSize(getPreferredSize());
  964. }
  965. public void show(Component invoker) {
  966. Container parent = null;
  967. if (invoker != null)
  968. parent = invoker.getParent();
  969. /*
  970. Find the top level window,
  971. if it has a layered pane,
  972. add to that, otherwise
  973. add to the window. */
  974. while(!(parent instanceof Window || parent instanceof Applet) && (parent!=null)) {
  975. parent = parent.getParent();
  976. }
  977. super.hide();
  978. if (parent instanceof RootPaneContainer) {
  979. parent = ((RootPaneContainer)parent).getLayeredPane();
  980. Point p = convertScreenLocationToParent(parent,desiredLocationX,desiredLocationY);
  981. this.setLocation(p.x,p.y);
  982. ((JLayeredPane)parent).add(this,JLayeredPane.POPUP_LAYER,0);
  983. } else {
  984. Point p = convertScreenLocationToParent(parent,desiredLocationX,desiredLocationY);
  985. this.setLocation(p.x,p.y);
  986. parent.add(this);
  987. }
  988. super.show();
  989. }
  990. public void hide() {
  991. Container parent = getParent();
  992. Rectangle r = this.getBounds();
  993. if(parent != null)
  994. parent.remove(this);
  995. parent.repaint(r.x,r.y,r.width,r.height);
  996. }
  997. public Rectangle getBoundsOnScreen() {
  998. Container parent = getParent();
  999. if(parent != null) {
  1000. Rectangle r = getBounds();
  1001. Point p;
  1002. p = convertParentLocationToScreen(parent,r.x,r.y);
  1003. r.x = p.x;
  1004. r.y = p.y;
  1005. return r;
  1006. } else
  1007. throw new Error("getBoundsOnScreen called on an invisible popup");
  1008. }
  1009. Point convertParentLocationToScreen(Container parent,int x,int y) {
  1010. Window parentWindow = null;
  1011. Rectangle r;
  1012. Container p;
  1013. Point pt;
  1014. for(p = this; p != null; p = p.getParent()) {
  1015. if(p instanceof Window) {
  1016. parentWindow = (Window)p;
  1017. break;
  1018. }
  1019. }
  1020. if(parentWindow != null) {
  1021. r = parentWindow.getBounds();
  1022. pt = new Point(x,y);
  1023. pt = SwingUtilities.convertPoint(parent,pt,null);
  1024. pt.x += r.x;
  1025. pt.y += r.y;
  1026. return pt;
  1027. } else
  1028. throw new Error("convertParentLocationToScreen: no window ancestor found"); }
  1029. Point convertScreenLocationToParent(Container parent,int x,int y) {
  1030. Window parentWindow = null;
  1031. Rectangle r;
  1032. for(Container p = parent; p != null; p = p.getParent()) {
  1033. if(p instanceof Window) {
  1034. parentWindow = (Window)p;
  1035. break;
  1036. }
  1037. }
  1038. if(parentWindow != null) {
  1039. Point p = new Point(x,y);
  1040. SwingUtilities.convertPointFromScreen(p,parent);
  1041. return p;
  1042. } else
  1043. throw new Error("convertScreenLocationToParent: no window ancestor found");
  1044. }
  1045. public void setLocationOnScreen(int x,int y) {
  1046. Container parent = getParent();
  1047. if(parent != null) {
  1048. Point p = convertScreenLocationToParent(parent,x,y);
  1049. this.setLocation(p.x,p.y);
  1050. } else {
  1051. desiredLocationX = x;
  1052. desiredLocationY = y;
  1053. }
  1054. }
  1055. }
  1056. }