Added
Link Here
|
1 |
/* |
2 |
* Sun Public License Notice |
3 |
* |
4 |
* The contents of this file are subject to the Sun Public License |
5 |
* Version 1.0 (the "License"). You may not use this file except in |
6 |
* compliance with the License. A copy of the License is available at |
7 |
* http://www.sun.com/ |
8 |
* |
9 |
* The Original Code is NetBeans. The Initial Developer of the Original |
10 |
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun |
11 |
* Microsystems, Inc. All Rights Reserved. |
12 |
*/ |
13 |
|
14 |
package org.netbeans.lib.editor.util; |
15 |
|
16 |
import java.io.IOException; |
17 |
import java.io.ObjectInputStream; |
18 |
import java.io.ObjectOutputStream; |
19 |
import java.io.Serializable; |
20 |
import java.util.ArrayList; |
21 |
import java.util.EventListener; |
22 |
import java.util.List; |
23 |
|
24 |
/** |
25 |
* Listener list that layers the maintained listeners |
26 |
* according to the given priority index. |
27 |
* <br> |
28 |
* Simply said it's an array of listener arrays. The priority index defines |
29 |
* the event listeners array holding all the listeners with the given priority index. |
30 |
* |
31 |
* @author Miloslav Metelka |
32 |
* @version 1.00 |
33 |
*/ |
34 |
|
35 |
public class PriorityListenerList implements Serializable { |
36 |
|
37 |
static final long serialVersionUID = 0L; |
38 |
|
39 |
private static final EventListener[] EMPTY_LISTENER_ARRAY = new EventListener[0]; |
40 |
|
41 |
private static final EventListener[][] EMPTY_LISTENER_ARRAY_ARRAY = new EventListener[0][]; |
42 |
|
43 |
private transient EventListener[][] listenersArray = EMPTY_LISTENER_ARRAY_ARRAY; |
44 |
|
45 |
/** |
46 |
* Add listener with the given priority. |
47 |
* |
48 |
* @param listener listener to be added. |
49 |
* @param priority >=0 index defining priority |
50 |
* with which the listener should be fired. |
51 |
* <br> |
52 |
* The higher the priority the sooner the listener will be fired. |
53 |
* <br> |
54 |
* It's guaranteed that all the listeners with higher priority index will be fired |
55 |
* sooner than listeners with lower priority. |
56 |
* <br> |
57 |
* The number of priority levels should be limited to reasonably |
58 |
* low number. |
59 |
* @throws IndexOutOfBoundsException when priority < 0 |
60 |
*/ |
61 |
public synchronized void add(EventListener listener, int priority) { |
62 |
EventListener[][] newListenersArray; |
63 |
if (priority >= listenersArray.length) { |
64 |
newListenersArray = new EventListener[priority + 1][]; |
65 |
System.arraycopy(listenersArray, 0, newListenersArray, 0, listenersArray.length); |
66 |
for (int i = listenersArray.length; i < priority; i++) { |
67 |
newListenersArray[i] = EMPTY_LISTENER_ARRAY; |
68 |
} |
69 |
newListenersArray[priority] = new EventListener[] { listener }; |
70 |
|
71 |
} else { // Add into existing listeners |
72 |
newListenersArray = (EventListener[][])listenersArray.clone(); |
73 |
EventListener[] listeners = listenersArray[priority]; |
74 |
EventListener[] newListeners = new EventListener[listeners.length + 1]; |
75 |
System.arraycopy(listeners, 0, newListeners, 1, listeners.length); |
76 |
newListeners[0] = listener; |
77 |
newListenersArray[priority] = newListeners; |
78 |
} |
79 |
|
80 |
listenersArray = newListenersArray; |
81 |
} |
82 |
|
83 |
/** |
84 |
* Remove listener with the given priority index. |
85 |
* |
86 |
* @param listener listener to be removed. |
87 |
* @param priority >=0 index defining priority |
88 |
* with which the listener was originally added. |
89 |
* <br> |
90 |
* If the listener was not added or it was added with different |
91 |
* priority then no action happens. |
92 |
* @throws IndexOutOfBoundsException when priority < 0 |
93 |
*/ |
94 |
public synchronized void remove(EventListener listener, int priority) { |
95 |
if (priority < listenersArray.length) { |
96 |
EventListener[] listeners = listenersArray[priority]; |
97 |
int index = listeners.length - 1; |
98 |
while (index >= 0 && listeners[index] != listener) { |
99 |
index--; |
100 |
} |
101 |
if (index >= 0) { |
102 |
EventListener[] newListeners; |
103 |
boolean removeHighestPriorityLevel; |
104 |
if (listeners.length == 1) { |
105 |
newListeners = EMPTY_LISTENER_ARRAY; |
106 |
removeHighestPriorityLevel = (priority == listenersArray.length - 1); |
107 |
} else { |
108 |
newListeners = new EventListener[listeners.length - 1]; |
109 |
System.arraycopy(listeners, 0, newListeners, 0, index); |
110 |
System.arraycopy(listeners, index + 1, newListeners, index, |
111 |
newListeners.length - index); |
112 |
removeHighestPriorityLevel = false; |
113 |
} |
114 |
|
115 |
EventListener[][] newListenersArray; |
116 |
if (removeHighestPriorityLevel) { |
117 |
newListenersArray = new EventListener[listenersArray.length - 1][]; |
118 |
System.arraycopy(listenersArray, 0, newListenersArray, 0, newListenersArray.length); |
119 |
} else { // levels count stays the same |
120 |
newListenersArray = (EventListener[][])listenersArray.clone(); |
121 |
newListenersArray[priority] = newListeners; |
122 |
} |
123 |
|
124 |
listenersArray = newListenersArray; |
125 |
} |
126 |
} |
127 |
} |
128 |
|
129 |
/** |
130 |
* Return the actual array of listeners arrays maintained by this listeners list. |
131 |
* <br> |
132 |
* <strong>WARNING!</strong> |
133 |
* Absolutely NO modification should be done on the contents of the returned |
134 |
* data. |
135 |
* |
136 |
* <p> |
137 |
* The higher index means sooner firing. Listeners with the same priority |
138 |
* are ordered so that the one added sooner has higher index than the one |
139 |
* added later. So the following firing mechanism should be used:<pre> |
140 |
* |
141 |
* private void fireMyEvent(MyEvent evt) { |
142 |
* EventListener[][] listenersArray = priorityListenerList.getListenersArray(); |
143 |
* for (int priority = listenersArray.length - 1; priority >= 0; priority--) { |
144 |
* EventListener[] listeners = listenersArray[priority]; |
145 |
* for (int i = listeners.length - 1; i >= 0; i--) { |
146 |
* ((MyListener)listeners[i]).notify(evt); |
147 |
* } |
148 |
* } |
149 |
* } |
150 |
* </pre> |
151 |
*/ |
152 |
public EventListener[][] getListenersArray() { |
153 |
return listenersArray; |
154 |
} |
155 |
|
156 |
// Serialization support. |
157 |
private void writeObject(ObjectOutputStream s) throws IOException { |
158 |
s.defaultWriteObject(); |
159 |
|
160 |
// Save serializable event listeners |
161 |
int priority = listenersArray.length - 1; // max priority |
162 |
s.writeInt(priority); // write max priority |
163 |
for (; priority >= 0; priority--) { |
164 |
EventListener[] listeners = listenersArray[priority]; |
165 |
// Write in opposite order of adding |
166 |
for (int i = 0; i < listeners.length; i++) { |
167 |
EventListener listener = listeners[i]; |
168 |
if (listener instanceof Serializable) { |
169 |
s.writeObject(listener); |
170 |
} |
171 |
} |
172 |
s.writeObject(null); |
173 |
} |
174 |
} |
175 |
|
176 |
private void readObject(ObjectInputStream s) |
177 |
throws IOException, ClassNotFoundException { |
178 |
s.defaultReadObject(); |
179 |
|
180 |
int priority = s.readInt(); |
181 |
listenersArray = (priority != -1) |
182 |
? new EventListener[priority + 1][] |
183 |
: EMPTY_LISTENER_ARRAY_ARRAY; |
184 |
|
185 |
for (; priority >= 0; priority--) { |
186 |
List listeners = new ArrayList(); |
187 |
EventListener listenerOrNull; |
188 |
while (null != (listenerOrNull = (EventListener)s.readObject())) { |
189 |
listeners.add(listenerOrNull); |
190 |
} |
191 |
listenersArray[priority] = (EventListener[])listeners.toArray( |
192 |
new EventListener[listeners.size()]); |
193 |
} |
194 |
} |
195 |
|
196 |
} |