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                ArrayList<IEventListener> ret = new ArrayList<IEventListener>();
189                for (EventPriority value : EventPriority.values())
190                {
191                    ret.addAll(getListeners(value));
192                }
193                listeners = ret.toArray(new IEventListener[0]);
194                rebuild = false;
195            }
196            
197            public void register(EventPriority priority, IEventListener listener)
198            {
199                priorities.get(priority.ordinal()).add(listener);
200                rebuild = true;
201            }
202            
203            public void unregister(IEventListener listener)
204            {
205                for(ArrayList<IEventListener> list : priorities)
206                {
207                    list.remove(listener);
208                }
209            }
210        }
211    }