    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    }