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)
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
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
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
;
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;
55 * protected final EventListenerList listeners = new EventListenerList();
56 * protected BarClosedEvent barClosedEvent = null;
58 * public void addBarListener(BarListener l)
60 * listeners.<a href="#add(java.lang.Class, java.util.EventListener)"
61 * >add</a>(BarListener.class, l);
64 * public void removeBarListener(BarListener l)
66 * listeners.<a href="#remove(java.lang.Class, java.util.EventListener)"
67 * >remove</a>(BarListener.class, l);
70 * protected void fireBarClosedEvent()
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)
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);
85 * }</pre></blockquote>
87 * @author Andrew Selkirk (aselkirk@sympatico.ca)
88 * @author Sascha Brawer (brawer@dandelis.ch)
90 public class EventListenerList
91 implements Serializable
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
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
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
)
143 if (listener
== null)
146 if (!t
.isInstance(listener
))
147 throw new IllegalArgumentException();
149 oldLength
= listenerList
.length
;
150 newList
= new Object
[oldLength
+ 2];
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
177 public int getListenerCount(Class t
)
180 for (int i
= 0; i
< listenerList
.length
; i
+= 2)
181 if (t
== listenerList
[i
])
189 * Get a list of listenerType/listener pairs
190 * @returns Listener list
192 public Object
[] getListenerList()
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
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
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.
222 public EventListener
[] getListeners(Class c
)
225 EventListener
[] result
;
227 count
= getListenerCount(c
);
228 result
= (EventListener
[]) Array
.newInstance(c
, count
);
230 for (int i
= 0; i
< listenerList
.length
; i
+= 2)
231 if (listenerList
[i
] == c
)
232 result
[f
++] = (EventListener
) listenerList
[i
+ 1];
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
;
256 if (listener
== null)
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
)
268 newList
= NO_LISTENERS
;
271 newList
= new Object
[oldLength
- 2];
273 System
.arraycopy(oldList
, 0, newList
, 0, i
);
274 if (i
< oldLength
- 2)
275 System
.arraycopy(oldList
, i
+ 2, newList
, i
,
278 listenerList
= newList
;
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();