Merge from mainline
[official-gcc.git] / libjava / classpath / javax / swing / event / EventListenerList.java
blob147d68ef184d2bedf9639cbdb2e68d87f2442193
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., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 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()
122 // Nothing to do here.
127 * Registers a listener of a specific type.
129 * @param t the type of the listener.
131 * @param listener the listener to add, which must be an instance of
132 * <code>t</code>, or of a subclass of <code>t</code>.
134 * @throws IllegalArgumentException if <code>listener</code> is not
135 * an instance of <code>t</code> (or a subclass thereof).
137 * @throws NullPointerException if <code>t</code> is <code>null</code>.
139 public void add(Class t, EventListener listener)
141 int oldLength;
142 Object[] newList;
144 if (listener == null)
145 return;
147 if (!t.isInstance(listener))
148 throw new IllegalArgumentException();
150 oldLength = listenerList.length;
151 newList = new Object[oldLength + 2];
152 if (oldLength > 0)
153 System.arraycopy(listenerList, 0, newList, 0, oldLength);
155 newList[oldLength] = t;
156 newList[oldLength + 1] = listener;
157 listenerList = newList;
162 * Determines the number of listeners.
164 public int getListenerCount()
166 return listenerList.length / 2;
171 * Determines the number of listeners of a particular class.
173 * @param t the type of listeners to be counted. In order to get
174 * counted, a subscribed listener must be exactly of class
175 * <code>t</code>. Thus, subclasses of <code>t</code> will not be
176 * counted.
178 public int getListenerCount(Class t)
180 int result = 0;
181 for (int i = 0; i < listenerList.length; i += 2)
182 if (t == listenerList[i])
183 ++result;
185 return result;
190 * Get a list of listenerType/listener pairs
191 * @returns Listener list
193 public Object[] getListenerList()
195 return listenerList;
200 * Retrieves the currently subscribed listeners of a particular
201 * type. For a listener to be returned, it must have been
202 * registered with exactly the type <code>c</code>; subclasses are
203 * not considered equal.
205 * <p>The returned array can always be cast to <code>c[]</code>.
206 * Since it is a newly allocated copy, the caller may arbitrarily
207 * modify the array.
209 * @param c the class which was passed to {@link #add}.
211 * @throws ClassCastException if <code>c</code> does not implement
212 * the {@link EventListener} interface.
214 * @throws NullPointerException if <code>c</code> is
215 * <code>null</code>.
217 * @returns an array of <code>c</code> whose elements are the
218 * currently subscribed listeners of the specified type. If there
219 * are no such listeners, an empty array is returned.
221 * @since 1.3
223 public EventListener[] getListeners(Class c)
225 int count, f;
226 EventListener[] result;
228 count = getListenerCount(c);
229 result = (EventListener[]) Array.newInstance(c, count);
230 f = 0;
231 for (int i = listenerList.length - 2; i >= 0; i -= 2)
232 if (listenerList[i] == c)
233 result[f++] = (EventListener) listenerList[i + 1];
235 return result;
240 * Removes a listener of a specific type.
242 * @param t the type of the listener.
244 * @param listener the listener to remove, which must be an instance
245 * of <code>t</code>, or of a subclass of <code>t</code>.
247 * @throws IllegalArgumentException if <code>listener</code> is not
248 * an instance of <code>t</code> (or a subclass thereof).
250 * @throws NullPointerException if <code>t</code> is <code>null</code>.
252 public void remove(Class t, EventListener listener)
254 Object[] oldList, newList;
255 int oldLength;
257 if (listener == null)
258 return;
260 if (!t.isInstance(listener))
261 throw new IllegalArgumentException();
263 oldList = listenerList;
264 oldLength = oldList.length;
265 for (int i = 0; i < oldLength; i += 2)
266 if (oldList[i] == t && oldList[i + 1] == listener)
268 if (oldLength == 2)
269 newList = NO_LISTENERS;
270 else
272 newList = new Object[oldLength - 2];
273 if (i > 0)
274 System.arraycopy(oldList, 0, newList, 0, i);
275 if (i < oldLength - 2)
276 System.arraycopy(oldList, i + 2, newList, i,
277 oldLength - 2 - i);
279 listenerList = newList;
280 return;
286 * Returns a string representation of this object that may be useful
287 * for debugging purposes.
289 public String toString()
291 StringBuffer buf = new StringBuffer("EventListenerList: ");
292 buf.append(listenerList.length / 2);
293 buf.append(" listeners: ");
294 for (int i = 0; i < listenerList.length; i += 2)
296 buf.append(" type ");
297 buf.append(((Class) listenerList[i]).getName());
298 buf.append(" listener ");
299 buf.append(listenerList[i + 1]);
301 return buf.toString();