2010年2月20日 星期六

加強版的EventDispatcher

已將這個類別納入開源專案之中,



加入四個新方法、一個新屬性:

getAllEventListenerType():Array
取得目前所有的事件偵聽式的type列表。

removeAllEventListener():void
移除所有的事件偵聽式。

removeEventListenerByType(type:String):Array
移除指定事件的所有偵聽式。

addEventListenerByArray(listeners:Array):void
加入陣列(用removeEventListenerByType所傳回的陣列)中的所有偵聽式。

eventSource屬性
若傳入的是IEventDispatcher的物件,
則會轉發所有AdvancedEventDispatcher上有偵聽的事件。
(注意,若是自訂的事件,請一定要覆寫clone方法)



AdvancedEventDispatcher
package tw.right929
{
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.IEventDispatcher;
    import flash.utils.Dictionary;
    
    /**
     * 加強版的EventDispatcher。
     */
    public class AdvancedEventDispatcher extends EventDispatcher
    {
        private var _eventSource:*;
        
        private var _map:Dictionary    =    new Dictionary();
        private var _mapCapture:Dictionary    =    new Dictionary();
        
        public function AdvancedEventDispatcher(target:IEventDispatcher=null)
        {
            super(target);
        }
        
        public function get eventSource():*
        {
            return _eventSource;
        }
        public function set eventSource(value:*):void
        {
            if(_eventSource == value)
                return;
            var old:*    =    _eventSource;
            bfs_eventSource(old , value);
            _eventSource    =    value;
            afs_eventSource(old , value);
        }
        private function bfs_eventSource(oldValue:* , newValue:*):void
        {
            if(oldValue && oldValue is IEventDispatcher)
            {
                for each(var type:* in _map)
                {
                    for each(var l:* in type)
                        oldValue.removeEventListener(l.type , _forwardEvent , l.useCapture);
                }
                for each(var type:* in _mapCapture)
                {
                    for each(var l:* in type)
                        oldValue.removeEventListener(l.type , _forwardEvent , l.useCapture);
                }
            }
        }
        private function afs_eventSource(oldValue:* , newValue:*):void
        {
            if(newValue && newValue is IEventDispatcher)
            {
                for each(var type:* in _map)
                {
                    for each(var l:* in type)
                        newValue.addEventListener(l.type , _forwardEvent , l.useCapture , l.priority , l.useWeakReference);
                }
                for each(var type:* in _mapCapture)
                {
                    for each(var l:* in type)
                        newValue.addEventListener(l.type , _forwardEvent , l.useCapture , l.priority , l.useWeakReference);
                }
            }
        }
        private function _forwardEvent(e:Event):void
        {
            dispatchEvent(e.clone());
        }

        override public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false) : void
        {
            if(_eventSource && _eventSource is IEventDispatcher)
                _eventSource.addEventListener(type , _forwardEvent , useCapture , priority , useWeakReference);
            
            super.addEventListener(type , listener , useCapture , priority , useWeakReference);
            
            if(useCapture)
            {
                if(_mapCapture[type])
                {
                    if(_mapCapture[type][listener])
                        return;
                    _mapCapture[type][listener]    =    new $Listener(type , listener , useCapture , priority , useWeakReference);
                }
                else
                {
                    _mapCapture[type]    =    new Dictionary();
                    _mapCapture[type][listener]    =    new $Listener(type , listener , useCapture , priority , useWeakReference);
                }
            }
            else
            {
                if(_map[type])
                {
                    if(_map[type][listener])
                        return;
                    _map[type][listener]    =    new $Listener(type , listener , useCapture , priority , useWeakReference);
                }
                else
                {
                    _map[type]    =    new Dictionary();
                    _map[type][listener]    =    new $Listener(type , listener , useCapture , priority , useWeakReference);
                }
            }
        }
        
        override public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false) : void
        {
            if(_eventSource && _eventSource is IEventDispatcher)
                _eventSource.removeEventListener(type , _forwardEvent , useCapture);
            
            super.removeEventListener(type, listener, useCapture);
            
            if(useCapture)
            {
                if(_mapCapture[type] && _mapCapture[type][listener])
                    delete _mapCapture[type][listener];
            }
            else
            {
                if(_map[type] && _map[type][listener])
                    delete _map[type][listener];
            }
        }
        
        /**
         * 取得目前所有的事件偵聽式的type列表。
         */
        public final function getAllEventListenerType():Array
        {
            var temp:Dictionary    =    new Dictionary(true);
            for(var type:* in _map)
            {
                for(var l:* in _map[type])
                {
                    temp[type]    =    type;
                    break;
                }
            }
            for(var type:* in _mapCapture)
            {
                for(var l:* in _mapCapture[type])
                {
                    temp[type]    =    type;
                    break;
                }
            }
            
            var result:Array    =    new Array();
            for(var type:* in temp)
                result.push(type);
            
            return result;
        }
        
        /**
         * 移除所有的事件偵聽式。
         */
        public final function removeAllEventListener():void
        {
            for(var type:* in _mapCapture)
            {
                for(var l:* in _mapCapture[type])
                    removeEventListener(type , l , true);
            }
            
            for(var type:* in _map)
            {
                for(var l:* in _map[type])
                    removeEventListener(type , l , false);
            }
        }
        
        /**
         * 移除指定事件的所有偵聽式。
         */
        public final function removeEventListenerByType(type:String):Array
        {
            var result:Array    =    new Array();
            
            if(_mapCapture[type])
            {
                for(var l:* in _mapCapture[type])
                {
                    result.push(_mapCapture[type][l]);
                    removeEventListener(type , l , true);
                }
            }
            
            if(_map[type])
            {
                for(var l:* in _map[type])
                {
                    result.push(_map[type][l]);
                    removeEventListener(type , l , false);
                }
            }
            
            return result;
        }
        
        /**
         * 加入陣列(用removeEventListenerByType所傳回的陣列)中的所有偵聽式。
         */
        public final function addEventListenerByArray(listeners:Array):void
        {
            for each(var l:* in listeners)
                addEventListener(l.type , l.listener , l.useCapture , l.priority , l.useWeakReference);
        }
    }
}

class $Listener
{
    public var type:String;
    public var listener:Function;
    public var useCapture:Boolean;
    public var priority:int;
    public var useWeakReference:Boolean;
    
    public function $Listener(type:String , listener:Function , useCapture:Boolean , priority:int , useWeakReference:Boolean)
    {
        this.type    =    type;
        this.listener    =    listener;
        this.useCapture    =    useCapture;
        this.priority    =    priority;
        this.useWeakReference    =    useWeakReference;
    }
}
測試
<?xml version="1.0" encoding="utf-8"?>
<s:Application creationComplete="init()" xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768">
    <fx:Script>
        <![CDATA[
            import tw.right929.AdvancedEventDispatcher;
            
            private var _aed:AdvancedEventDispatcher    =    new AdvancedEventDispatcher();
            
            private function init():void
            {
                _aed.addEventListener("onE" , onE);
                _aed.addEventListener("onE" , onE , true);
                _aed.addEventListener("onF" , onF);
                trace(_aed.getAllEventListenerType());//onE,onF
                
                _aed.dispatchEvent(new Event("onE"));//onE
                _aed.dispatchEvent(new Event("onF"));//onF
                var temp:Array    =    _aed.removeEventListenerByType("onE");
                _aed.dispatchEvent(new Event("onE"));
                _aed.dispatchEvent(new Event("onF"));//onF
                _aed.addEventListenerByArray(temp);
                _aed.dispatchEvent(new Event("onE"));//onE
                _aed.dispatchEvent(new Event("onF"));//onF
                _aed.removeAllEventListener();
                _aed.dispatchEvent(new Event("onE"));
                _aed.dispatchEvent(new Event("onF"));
                
                trace("測試eventSource屬性");
                _aed.addEventListener("onE" , onE);
                _aed.addEventListener("onE" , onE , true);
                _aed.addEventListener("onF" , onF);
                var s:Sprite    =    new Sprite();
                _aed.eventSource    =    s;
                s.dispatchEvent(new Event("onE"));//onE
                s.dispatchEvent(new Event("onF"));//onF
                _aed.removeEventListener("onF" , onF);
                s.dispatchEvent(new Event("onE"));//onE
                s.dispatchEvent(new Event("onF"));
                _aed.addEventListener("onF" , onF);
                s.dispatchEvent(new Event("onE"));//onE
                s.dispatchEvent(new Event("onF"));//onF
            }
            
            private function onE(e:Event):void
            {
                trace("onE");
            }
            private function onF(e:Event):void
            {
                trace("onF");
            }
        ]]>
    </fx:Script>
</s:Application>

沒有留言:

張貼留言

追蹤者