blob: 694bc5df08d9fec5430e10f1b7172640bbb78d61 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package javax.swing;
27
28
29import javax.swing.event.*;
30import java.awt.event.*;
31
32import java.awt.Component;
33import java.awt.Container;
34import java.awt.Window;
35import java.beans.PropertyChangeListener;
36import java.beans.PropertyChangeEvent;
37
38import java.io.Serializable;
39
40
41/**
42 * @author Dave Moore
43 */
44
45class AncestorNotifier implements ComponentListener, PropertyChangeListener, Serializable
46{
47 Component firstInvisibleAncestor;
48 EventListenerList listenerList = new EventListenerList();
49 JComponent root;
50
51 AncestorNotifier(JComponent root) {
52 this.root = root;
53 addListeners(root, true);
54 }
55
56 void addAncestorListener(AncestorListener l) {
57 listenerList.add(AncestorListener.class, l);
58 }
59
60 void removeAncestorListener(AncestorListener l) {
61 listenerList.remove(AncestorListener.class, l);
62 }
63
64 AncestorListener[] getAncestorListeners() {
65 return (AncestorListener[])listenerList.getListeners(AncestorListener.class);
66 }
67
68 /**
69 * Notify all listeners that have registered interest for
70 * notification on this event type. The event instance
71 * is lazily created using the parameters passed into
72 * the fire method.
73 * @see EventListenerList
74 */
75 protected void fireAncestorAdded(JComponent source, int id, Container ancestor, Container ancestorParent) {
76 // Guaranteed to return a non-null array
77 Object[] listeners = listenerList.getListenerList();
78 // Process the listeners last to first, notifying
79 // those that are interested in this event
80 for (int i = listeners.length-2; i>=0; i-=2) {
81 if (listeners[i]==AncestorListener.class) {
82 // Lazily create the event:
83 AncestorEvent ancestorEvent =
84 new AncestorEvent(source, id, ancestor, ancestorParent);
85 ((AncestorListener)listeners[i+1]).ancestorAdded(ancestorEvent);
86 }
87 }
88 }
89
90 /**
91 * Notify all listeners that have registered interest for
92 * notification on this event type. The event instance
93 * is lazily created using the parameters passed into
94 * the fire method.
95 * @see EventListenerList
96 */
97 protected void fireAncestorRemoved(JComponent source, int id, Container ancestor, Container ancestorParent) {
98 // Guaranteed to return a non-null array
99 Object[] listeners = listenerList.getListenerList();
100 // Process the listeners last to first, notifying
101 // those that are interested in this event
102 for (int i = listeners.length-2; i>=0; i-=2) {
103 if (listeners[i]==AncestorListener.class) {
104 // Lazily create the event:
105 AncestorEvent ancestorEvent =
106 new AncestorEvent(source, id, ancestor, ancestorParent);
107 ((AncestorListener)listeners[i+1]).ancestorRemoved(ancestorEvent);
108 }
109 }
110 }
111 /**
112 * Notify all listeners that have registered interest for
113 * notification on this event type. The event instance
114 * is lazily created using the parameters passed into
115 * the fire method.
116 * @see EventListenerList
117 */
118 protected void fireAncestorMoved(JComponent source, int id, Container ancestor, Container ancestorParent) {
119 // Guaranteed to return a non-null array
120 Object[] listeners = listenerList.getListenerList();
121 // Process the listeners last to first, notifying
122 // those that are interested in this event
123 for (int i = listeners.length-2; i>=0; i-=2) {
124 if (listeners[i]==AncestorListener.class) {
125 // Lazily create the event:
126 AncestorEvent ancestorEvent =
127 new AncestorEvent(source, id, ancestor, ancestorParent);
128 ((AncestorListener)listeners[i+1]).ancestorMoved(ancestorEvent);
129 }
130 }
131 }
132
133 void removeAllListeners() {
134 removeListeners(root);
135 }
136
137 void addListeners(Component ancestor, boolean addToFirst) {
138 Component a;
139
140 firstInvisibleAncestor = null;
141 for (a = ancestor;
142 firstInvisibleAncestor == null;
143 a = a.getParent()) {
144 if (addToFirst || a != ancestor) {
145 a.addComponentListener(this);
146
147 if (a instanceof JComponent) {
148 JComponent jAncestor = (JComponent)a;
149
150 jAncestor.addPropertyChangeListener(this);
151 }
152 }
153 if (!a.isVisible() || a.getParent() == null || a instanceof Window) {
154 firstInvisibleAncestor = a;
155 }
156 }
157 if (firstInvisibleAncestor instanceof Window &&
158 firstInvisibleAncestor.isVisible()) {
159 firstInvisibleAncestor = null;
160 }
161 }
162
163 void removeListeners(Component ancestor) {
164 Component a;
165 for (a = ancestor; a != null; a = a.getParent()) {
166 a.removeComponentListener(this);
167 if (a instanceof JComponent) {
168 JComponent jAncestor = (JComponent)a;
169 jAncestor.removePropertyChangeListener(this);
170 }
171 if (a == firstInvisibleAncestor || a instanceof Window) {
172 break;
173 }
174 }
175 }
176
177 public void componentResized(ComponentEvent e) {}
178
179 public void componentMoved(ComponentEvent e) {
180 Component source = e.getComponent();
181
182 fireAncestorMoved(root, AncestorEvent.ANCESTOR_MOVED,
183 (Container)source, source.getParent());
184 }
185
186 public void componentShown(ComponentEvent e) {
187 Component ancestor = e.getComponent();
188
189 if (ancestor == firstInvisibleAncestor) {
190 addListeners(ancestor, false);
191 if (firstInvisibleAncestor == null) {
192 fireAncestorAdded(root, AncestorEvent.ANCESTOR_ADDED,
193 (Container)ancestor, ancestor.getParent());
194 }
195 }
196 }
197
198 public void componentHidden(ComponentEvent e) {
199 Component ancestor = e.getComponent();
200 boolean needsNotify = firstInvisibleAncestor == null;
201
202 if ( !(ancestor instanceof Window) ) {
203 removeListeners(ancestor.getParent());
204 }
205 firstInvisibleAncestor = ancestor;
206 if (needsNotify) {
207 fireAncestorRemoved(root, AncestorEvent.ANCESTOR_REMOVED,
208 (Container)ancestor, ancestor.getParent());
209 }
210 }
211
212 public void propertyChange(PropertyChangeEvent evt) {
213 String s = evt.getPropertyName();
214
215 if (s!=null && (s.equals("parent") || s.equals("ancestor"))) {
216 JComponent component = (JComponent)evt.getSource();
217
218 if (evt.getNewValue() != null) {
219 if (component == firstInvisibleAncestor) {
220 addListeners(component, false);
221 if (firstInvisibleAncestor == null) {
222 fireAncestorAdded(root, AncestorEvent.ANCESTOR_ADDED,
223 component, component.getParent());
224 }
225 }
226 } else {
227 boolean needsNotify = firstInvisibleAncestor == null;
228 Container oldParent = (Container)evt.getOldValue();
229
230 removeListeners(oldParent);
231 firstInvisibleAncestor = component;
232 if (needsNotify) {
233 fireAncestorRemoved(root, AncestorEvent.ANCESTOR_REMOVED,
234 component, oldParent);
235 }
236 }
237 }
238 }
239}