Merge from the pain train
[official-gcc.git] / libjava / javax / swing / event / EventListenerList.java
blob226cac179169ed17f66ece6df921484ba4d50e58
1 /* EventListenerList.java --
2 Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package javax.swing.event;
40 import java.io.Serializable;
41 import java.lang.reflect.Array;
42 import java.util.EventListener;
45 /**
46 * A utility class for keeping track of {@link EventListener}s.
48 * <p><b>Example for using this class:</b>
50 * <blockquote><pre> import java.util.EventListener;
51 * import javax.swing.event.EventListenerList;
53 * class Foo
54 * {
55 * protected final EventListenerList listeners = new EventListenerList();
56 * protected BarClosedEvent barClosedEvent = null;
58 * public void addBarListener(BarListener l)
59 * {
60 * listeners.<a href="#add(java.lang.Class, java.util.EventListener)"
61 * >add</a>(BarListener.class, l);
62 * }
64 * public void removeBarListener(BarListener l)
65 * {
66 * listeners.<a href="#remove(java.lang.Class, java.util.EventListener)"
67 * >remove</a>(BarListener.class, l);
68 * }
70 * protected void fireBarClosedEvent()
71 * {
72 * Object[] l = listeners.<a href="#getListenerList()"
73 * >getListenerList()</a>;
75 * for (int i = l.length - 2; i >= 0; i -= 2)
76 * if (l[i] == BarListener.class)
77 * {
78 * // Create the event on demand, when it is needed the first time.
79 * if (barClosedEvent == null)
80 * barClosedEvent = new BarClosedEvent(this);
82 * ((BarClosedListener) l[i + 1]).barClosed(barClosedEvent);
83 * }
84 * }
85 * }</pre></blockquote>
87 * @author Andrew Selkirk (aselkirk@sympatico.ca)
88 * @author Sascha Brawer (brawer@dandelis.ch)
90 public class EventListenerList
91 implements Serializable
93 /**
94 * An ID for serializing instances of this class; verified with the
95 * serialver tool of Sun J2SE 1.4.1_01.
97 static final long serialVersionUID = -5677132037850737084L;
101 * An empty array that is shared by all instances of this class that
102 * have no listeners.
104 private static final Object[] NO_LISTENERS = new Object[0];
108 * An array with all currently registered listeners. The array has
109 * twice as many elements as there are listeners. For an even
110 * integer <code>i</code>, <code>listenerList[i]</code> indicates
111 * the registered class, and <code>listenerList[i+1]</code> is the
112 * listener.
114 protected transient Object[] listenerList = NO_LISTENERS;
118 * EventListenerList constructor
120 public EventListenerList()
126 * Registers a listener of a specific type.
128 * @param t the type of the listener.
130 * @param listener the listener to add, which must be an instance of
131 * <code>t</code>, or of a subclass of <code>t</code>.
133 * @throws IllegalArgumentException if <code>listener</code> is not
134 * an instance of <code>t</code> (or a subclass thereof).
136 * @throws Exception if <code>t</code> is <code>null</code>.
138 public void add(Class t, EventListener listener)
140 int oldLength;
141 Object[] newList;
143 if (listener == null)
144 return;
146 if (!t.isInstance(listener))
147 throw new IllegalArgumentException();
149 oldLength = listenerList.length;
150 newList = new Object[oldLength + 2];
151 if (oldLength > 0)
152 System.arraycopy(listenerList, 0, newList, 0, oldLength);
154 newList[oldLength] = t;
155 newList[oldLength + 1] = listener;
156 listenerList = newList;
161 * Determines the number of listeners.
163 public int getListenerCount()
165 return listenerList.length / 2;
170 * Determines the number of listeners of a particular class.
172 * @param t the type of listeners to be counted. In order to get
173 * counted, a subscribed listener must be exactly of class
174 * <code>t</code>. Thus, subclasses of <code>t</code> will not be
175 * counted.
177 public int getListenerCount(Class t)
179 int result = 0;
180 for (int i = 0; i < listenerList.length; i += 2)
181 if (t == listenerList[i])
182 ++result;
184 return result;
189 * Get a list of listenerType/listener pairs
190 * @returns Listener list
192 public Object[] getListenerList()
194 return listenerList;
199 * Retrieves the currently subscribed listeners of a particular
200 * type. For a listener to be returned, it must have been
201 * registered with exactly the type <code>c</code>; subclasses are
202 * not considered equal.
204 * <p>The returned array can always be cast to <code>c[]</code>.
205 * Since it is a newly allocated copy, the caller may arbitrarily
206 * modify the array.
208 * @param c the class which was passed to {@link #add}.
210 * @throws ClassCastException if <code>c</code> does not implement
211 * the {@link EventListener} interface.
213 * @throws NullPointerException if <code>c</code> is
214 * <code>null</code>.
216 * @returns an array of <code>c</code> whose elements are the
217 * currently subscribed listeners of the specified type. If there
218 * are no such listeners, an empty array is returned.
220 * @since 1.3
222 public EventListener[] getListeners(Class c)
224 int count, f;
225 EventListener[] result;
227 count = getListenerCount(c);
228 result = (EventListener[]) Array.newInstance(c, count);
229 f = 0;
230 for (int i = 0; i < listenerList.length; i += 2)
231 if (listenerList[i] == c)
232 result[f++] = (EventListener) listenerList[i + 1];
234 return result;
239 * Removes a listener of a specific type.
241 * @param t the type of the listener.
243 * @param listener the listener to remove, which must be an instance
244 * of <code>t</code>, or of a subclass of <code>t</code>.
246 * @throws IllegalArgumentException if <code>listener</code> is not
247 * an instance of <code>t</code> (or a subclass thereof).
249 * @throws Exception if <code>t</code> is <code>null</code>.
251 public void remove(Class t, EventListener listener)
253 Object[] oldList, newList;
254 int oldLength;
256 if (listener == null)
257 return;
259 if (!t.isInstance(listener))
260 throw new IllegalArgumentException();
262 oldList = listenerList;
263 oldLength = oldList.length;
264 for (int i = 0; i < oldLength; i += 2)
265 if (oldList[i] == t && oldList[i + 1] == listener)
267 if (oldLength == 2)
268 newList = NO_LISTENERS;
269 else
271 newList = new Object[oldLength - 2];
272 if (i > 0)
273 System.arraycopy(oldList, 0, newList, 0, i);
274 if (i < oldLength - 2)
275 System.arraycopy(oldList, i + 2, newList, i,
276 oldLength - 2 - i);
278 listenerList = newList;
279 return;
285 * Returns a string representation of this object that may be useful
286 * for debugging purposes.
288 public String toString()
290 StringBuffer buf = new StringBuffer("EventListenerList: ");
291 buf.append(listenerList.length / 2);
292 buf.append(" listeners: ");
293 for (int i = 0; i < listenerList.length; i += 2)
295 buf.append(" type ");
296 buf.append(((Class) listenerList[i]).getName());
297 buf.append(" listener ");
298 buf.append(listenerList[i + 1]);
300 return buf.toString();