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 }