001 package net.minecraftforge.event;
002
003 import java.util.*;
004
005
006 public class ListenerList
007 {
008 private static ArrayList<ListenerList> allLists = new ArrayList<ListenerList>();
009 private static int maxSize = 0;
010
011 private ListenerList parent;
012 private ListenerListInst[] lists = new ListenerListInst[0];
013
014 public ListenerList()
015 {
016 allLists.add(this);
017 resizeLists(maxSize);
018 }
019
020 public ListenerList(ListenerList parent)
021 {
022 allLists.add(this);
023 this.parent = parent;
024 resizeLists(maxSize);
025 }
026
027 public static void resize(int max)
028 {
029 if (max <= maxSize)
030 {
031 return;
032 }
033 for (ListenerList list : allLists)
034 {
035 list.resizeLists(max);
036 }
037 maxSize = max;
038 }
039
040 public void resizeLists(int max)
041 {
042 if (parent != null)
043 {
044 parent.resizeLists(max);
045 }
046
047 if (lists.length >= max)
048 {
049 return;
050 }
051
052 ListenerListInst[] newList = new ListenerListInst[max];
053 int x = 0;
054 for (; x < lists.length; x++)
055 {
056 newList[x] = lists[x];
057 }
058 for(; x < max; x++)
059 {
060 if (parent != null)
061 {
062 newList[x] = new ListenerListInst(parent.getInstance(x));
063 }
064 else
065 {
066 newList[x] = new ListenerListInst();
067 }
068 }
069 lists = newList;
070 }
071
072 public static void clearBusID(int id)
073 {
074 for (ListenerList list : allLists)
075 {
076 list.lists[id].dispose();
077 }
078 }
079
080 protected ListenerListInst getInstance(int id)
081 {
082 return lists[id];
083 }
084
085 public IEventListener[] getListeners(int id)
086 {
087 return lists[id].getListeners();
088 }
089
090 public void register(int id, EventPriority priority, IEventListener listener)
091 {
092 lists[id].register(priority, listener);
093 }
094
095 public void unregister(int id, IEventListener listener)
096 {
097 lists[id].unregister(listener);
098 }
099
100 public static void unregiterAll(int id, IEventListener listener)
101 {
102 for (ListenerList list : allLists)
103 {
104 list.unregister(id, listener);
105 }
106 }
107
108 private class ListenerListInst
109 {
110 private boolean rebuild = true;
111 private IEventListener[] listeners;
112 private ArrayList<ArrayList<IEventListener>> priorities;
113 private ListenerListInst parent;
114
115 private ListenerListInst()
116 {
117 int count = EventPriority.values().length;
118 priorities = new ArrayList<ArrayList<IEventListener>>(count);
119
120 for (int x = 0; x < count; x++)
121 {
122 priorities.add(new ArrayList<IEventListener>());
123 }
124 }
125
126 public void dispose()
127 {
128 for (ArrayList<IEventListener> listeners : priorities)
129 {
130 listeners.clear();
131 }
132 priorities.clear();
133 parent = null;
134 listeners = null;
135 }
136
137 private ListenerListInst(ListenerListInst parent)
138 {
139 this();
140 this.parent = parent;
141 }
142
143 /**
144 * Returns a ArrayList containing all listeners for this event,
145 * and all parent events for the specified priority.
146 *
147 * The list is returned with the listeners for the children events first.
148 *
149 * @param priority The Priority to get
150 * @return ArrayList containing listeners
151 */
152 public ArrayList<IEventListener> getListeners(EventPriority priority)
153 {
154 ArrayList<IEventListener> ret = new ArrayList<IEventListener>(priorities.get(priority.ordinal()));
155 if (parent != null)
156 {
157 ret.addAll(parent.getListeners(priority));
158 }
159 return ret;
160 }
161
162 /**
163 * Returns a full list of all listeners for all priority levels.
164 * Including all parent listeners.
165 *
166 * List is returned in proper priority order.
167 *
168 * Automatically rebuilds the internal Array cache if its information is out of date.
169 *
170 * @return Array containing listeners
171 */
172 public IEventListener[] getListeners()
173 {
174 if (shouldRebuild()) buildCache();
175 return listeners;
176 }
177
178 protected boolean shouldRebuild()
179 {
180 return rebuild || (parent != null && parent.shouldRebuild());
181 }
182
183 /**
184 * Rebuild the local Array of listeners, returns early if there is no work to do.
185 */
186 private void buildCache()
187 {
188 if(parent != null && parent.shouldRebuild())
189 {
190 parent.buildCache();
191 }
192
193 ArrayList<IEventListener> ret = new ArrayList<IEventListener>();
194 for (EventPriority value : EventPriority.values())
195 {
196 ret.addAll(getListeners(value));
197 }
198 listeners = ret.toArray(new IEventListener[0]);
199 rebuild = false;
200 }
201
202 public void register(EventPriority priority, IEventListener listener)
203 {
204 priorities.get(priority.ordinal()).add(listener);
205 rebuild = true;
206 }
207
208 public void unregister(IEventListener listener)
209 {
210 for(ArrayList<IEventListener> list : priorities)
211 {
212 list.remove(listener);
213 }
214 }
215 }
216 }