1. /*
  2. * @(#)AncestorNotifier.java 1.13 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 javax.swing;
  8. import javax.swing.event.*;
  9. import java.awt.event.*;
  10. import java.awt.Component;
  11. import java.awt.Container;
  12. import java.awt.Window;
  13. import java.beans.PropertyChangeListener;
  14. import java.beans.PropertyChangeEvent;
  15. import java.io.Serializable;
  16. /**
  17. * @version 1.13 11/29/01
  18. * @author Dave Moore
  19. */
  20. class AncestorNotifier implements ComponentListener, PropertyChangeListener, Serializable
  21. {
  22. Component firstInvisibleAncestor;
  23. EventListenerList listenerList = new EventListenerList();
  24. JComponent root;
  25. AncestorNotifier(JComponent root) {
  26. this.root = root;
  27. addListeners(root, true);
  28. }
  29. void addAncestorListener(AncestorListener l) {
  30. listenerList.add(AncestorListener.class, l);
  31. }
  32. void removeAncestorListener(AncestorListener l) {
  33. listenerList.remove(AncestorListener.class, l);
  34. }
  35. /*
  36. * Notify all listeners that have registered interest for
  37. * notification on this event type. The event instance
  38. * is lazily created using the parameters passed into
  39. * the fire method.
  40. * @see EventListenerList
  41. */
  42. protected void fireAncestorAdded(JComponent source, int id, Container ancestor, Container ancestorParent) {
  43. // Guaranteed to return a non-null array
  44. Object[] listeners = listenerList.getListenerList();
  45. // Process the listeners last to first, notifying
  46. // those that are interested in this event
  47. for (int i = listeners.length-2; i>=0; i-=2) {
  48. if (listeners[i]==AncestorListener.class) {
  49. // Lazily create the event:
  50. AncestorEvent ancestorEvent =
  51. new AncestorEvent(source, id, ancestor, ancestorParent);
  52. ((AncestorListener)listeners[i+1]).ancestorAdded(ancestorEvent);
  53. }
  54. }
  55. }
  56. /*
  57. * Notify all listeners that have registered interest for
  58. * notification on this event type. The event instance
  59. * is lazily created using the parameters passed into
  60. * the fire method.
  61. * @see EventListenerList
  62. */
  63. protected void fireAncestorRemoved(JComponent source, int id, Container ancestor, Container ancestorParent) {
  64. // Guaranteed to return a non-null array
  65. Object[] listeners = listenerList.getListenerList();
  66. // Process the listeners last to first, notifying
  67. // those that are interested in this event
  68. for (int i = listeners.length-2; i>=0; i-=2) {
  69. if (listeners[i]==AncestorListener.class) {
  70. // Lazily create the event:
  71. AncestorEvent ancestorEvent =
  72. new AncestorEvent(source, id, ancestor, ancestorParent);
  73. ((AncestorListener)listeners[i+1]).ancestorRemoved(ancestorEvent);
  74. }
  75. }
  76. }
  77. /*
  78. * Notify all listeners that have registered interest for
  79. * notification on this event type. The event instance
  80. * is lazily created using the parameters passed into
  81. * the fire method.
  82. * @see EventListenerList
  83. */
  84. protected void fireAncestorMoved(JComponent source, int id, Container ancestor, Container ancestorParent) {
  85. // Guaranteed to return a non-null array
  86. Object[] listeners = listenerList.getListenerList();
  87. // Process the listeners last to first, notifying
  88. // those that are interested in this event
  89. for (int i = listeners.length-2; i>=0; i-=2) {
  90. if (listeners[i]==AncestorListener.class) {
  91. // Lazily create the event:
  92. AncestorEvent ancestorEvent =
  93. new AncestorEvent(source, id, ancestor, ancestorParent);
  94. ((AncestorListener)listeners[i+1]).ancestorMoved(ancestorEvent);
  95. }
  96. }
  97. }
  98. void removeAllListeners() {
  99. removeListeners(root);
  100. }
  101. void addListeners(Component ancestor, boolean addToFirst) {
  102. Component a;
  103. firstInvisibleAncestor = null;
  104. for (a = ancestor;
  105. firstInvisibleAncestor == null;
  106. a = a.getParent()) {
  107. if (addToFirst || a != ancestor) {
  108. a.addComponentListener(this);
  109. if (a instanceof JComponent) {
  110. JComponent jAncestor = (JComponent)a;
  111. jAncestor.addPropertyChangeListener(this);
  112. }
  113. }
  114. if (!a.isVisible() || a.getParent() == null) {
  115. firstInvisibleAncestor = a;
  116. }
  117. }
  118. if (firstInvisibleAncestor instanceof Window) {
  119. firstInvisibleAncestor = null;
  120. }
  121. }
  122. void removeListeners(Component ancestor) {
  123. Component a;
  124. for (a = ancestor; a != null; a = a.getParent()) {
  125. a.removeComponentListener(this);
  126. if (a instanceof JComponent) {
  127. JComponent jAncestor = (JComponent)a;
  128. jAncestor.removePropertyChangeListener(this);
  129. }
  130. if (a == firstInvisibleAncestor) {
  131. break;
  132. }
  133. }
  134. }
  135. public void componentResized(ComponentEvent e) {}
  136. public void componentMoved(ComponentEvent e) {
  137. Component source = e.getComponent();
  138. fireAncestorMoved(root, AncestorEvent.ANCESTOR_MOVED,
  139. (Container)source, source.getParent());
  140. }
  141. public void componentShown(ComponentEvent e) {
  142. Component ancestor = e.getComponent();
  143. if (ancestor == firstInvisibleAncestor) {
  144. addListeners(ancestor, false);
  145. if (firstInvisibleAncestor == null) {
  146. fireAncestorAdded(root, AncestorEvent.ANCESTOR_ADDED,
  147. (Container)ancestor, ancestor.getParent());
  148. }
  149. }
  150. }
  151. public void componentHidden(ComponentEvent e) {
  152. Component ancestor = e.getComponent();
  153. boolean needsNotify = firstInvisibleAncestor == null;
  154. removeListeners(ancestor.getParent());
  155. firstInvisibleAncestor = ancestor;
  156. if (needsNotify) {
  157. fireAncestorRemoved(root, AncestorEvent.ANCESTOR_REMOVED,
  158. (Container)ancestor, ancestor.getParent());
  159. }
  160. }
  161. public void propertyChange(PropertyChangeEvent evt) {
  162. String s = evt.getPropertyName();
  163. if (s!=null && (s.equals("parent") || s.equals("ancestor"))) {
  164. JComponent component = (JComponent)evt.getSource();
  165. if (evt.getNewValue() != null) {
  166. if (component == firstInvisibleAncestor) {
  167. addListeners(component, false);
  168. if (firstInvisibleAncestor == null) {
  169. fireAncestorAdded(root, AncestorEvent.ANCESTOR_ADDED,
  170. component, component.getParent());
  171. }
  172. }
  173. } else {
  174. boolean needsNotify = firstInvisibleAncestor == null;
  175. Container oldParent = (Container)evt.getOldValue();
  176. removeListeners(oldParent);
  177. firstInvisibleAncestor = component;
  178. if (needsNotify) {
  179. fireAncestorRemoved(root, AncestorEvent.ANCESTOR_REMOVED,
  180. component, oldParent);
  181. }
  182. }
  183. }
  184. }
  185. }