// // Licensed under the MIT License // // Copyright (C) 2008 TAKANAWA Tomoaki (http://nutsu.com) and // Spark project (www.libspark.org) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // package snapfit.events { import flash.events.Event; import flash.events.EventDispatcher; import flash.events.IEventDispatcher; import flash.utils.Proxy; import flash.utils.flash_proxy; /** * FAdapter * @author nutsu * @version 0.2 */ dynamic public class FAdapter extends Proxy implements IAdapter { private var _dispatcher:IEventDispatcher; private var _listeners:Object; private var _useCapture:Boolean = false; private var _priority:int = 0; private var _useWeakReference:Boolean = false; public function FAdapter( dispatcher_:IEventDispatcher=null ) { _dispatcher = (dispatcher_) ? dispatcher_ : new EventDispatcher(); _listeners = { }; } public function get dispatcher():IEventDispatcher { return _dispatcher; } public function set dispatcher(value:IEventDispatcher):void { abort(); _dispatcher = value; resume(); } public function setDefaultProps( useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false ):void { _useCapture = useCapture; _priority = priority; _useWeakReference = useWeakReference; } public function addEventListener( type:String, handler:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false ):void { this[type] = new $listener( this, type, handler, useCapture, priority, useWeakReference ); } public function removeEventListener( type:String ):void { delete this[type]; } public function dispatchEvent( e:Event ):Boolean { return _dispatcher.dispatchEvent( e ); } //------------------------------------------------------------------------------------UTIL /** * @param eventType * @return result code. * @see FAdapterCheckResult */ public function check( eventType:String ):int { if ( _listeners[eventType] ) if ( _dispatcher.hasEventListener(eventType) ) if ( _listeners[eventType].active ) return FAdapterCheckResult.ACTIVE; else return FAdapterCheckResult.HAS_BUT_NOT_ACTIVE; else if( !_listeners[eventType].active ) return FAdapterCheckResult.NOT_ACTIVE; else return FAdapterCheckResult.NOT_HAS_BUT_ACTIVE; else if ( _dispatcher.hasEventListener(eventType) ) return FAdapterCheckResult.HAS_UNKNOWN; else return FAdapterCheckResult.NOT_EXISTS; } /** * @param eventType default:abort all */ public function abort( eventType:String=null ):void { if ( eventType==null ) { for each ( var obj:$listener in _listeners ) _remove( obj ); } else if( check(eventType)==FAdapterCheckResult.ACTIVE ) { _remove( _listeners[eventType] ); } } /** * @param eventType default:resume all */ public function resume( eventType:String=null ):void { if ( eventType==null ) { for each ( var obj:$listener in _listeners ) _add( obj ); } else if( check(eventType)==FAdapterCheckResult.NOT_ACTIVE ) { _add( _listeners[eventType] ); } } /** * @param active_kind 1:active, 0:not active, default:all * @return String[] */ public function getTypes( active_kind:int=-1 ):Array { var res:Array = []; var obj:$listener; if ( active_kind == 1 ) { for each ( obj in _listeners ) if( obj.active ) res.push( obj.type ); } else if ( active_kind == 0 ) { for each ( obj in _listeners ) if( !obj.active ) res.push( obj.type ); } else { for each ( obj in _listeners ) res.push( obj.type ); } return res; } public function removeAll():void { for ( var eventType in _listeners ) delete this[eventType]; } //------------------------------------------------------------------------------------ filter /** * イベント送出後に listener を remove します。 */ public static function oneTime( lo:* ):Boolean { if ( lo is $listener ) { var active_listener:Boolean = lo._active; if( active_listener ) lo._ref._remove( lo ); lo._handler = function( e:* ):void { lo._targetHandler.apply( null, [e] ); delete lo._ref[lo._type]; }; if( active_listener ) lo._ref._add( lo ); return true; } else { return false; } } /** * filterfunc が true を返すときに、イベントが送出されます. * @param lo adapter[eventType] * @param filterfunc filter function * @param remove */ public static function filter( lo:*, filterfunc:Function, remove:Boolean=false ):Boolean { if ( lo is $listener ) { var active_listener:Boolean = lo._active; if ( active_listener ) lo._ref._remove( lo ); if ( remove ) { lo._handler = function( e:* ):void { if ( filterfunc( e ) ) lo._targetHandler.apply( null, [e] ); else delete lo._ref[lo._type]; }; } else { lo._handler = function( e:* ):void { if( filterfunc( e ) ) lo._targetHandler.apply( null, [e] ); }; } if( active_listener ) lo._ref._add( lo ); return true; } else { return false; } } /** * onTime() filter() の設定を解除します. */ public static function clearFilter( lo:* ):Boolean { if ( lo is $listener ) { var active_listener:Boolean = lo._active; if( active_listener ) lo._ref._remove( lo ); lo._handler = lo._targetHandler; if( active_listener ) lo._ref._add( lo ); return true; } else { return false; } } //------------------------------------------------------------------------------------ADD_REMOVE private function _add( lo:$listener ):void { if ( !lo.active ) { _dispatcher.addEventListener( lo._type, lo._handler, lo._useCapture, lo._priority, lo._useWeakReference ); lo._active = true; } } private function _remove( lo:$listener ):void { if ( _dispatcher.hasEventListener( lo._type ) ) { _dispatcher.removeEventListener( lo._type, lo._handler, lo._useCapture ); lo._active = false; } } //------------------------------------------------------------------------------------PROXY override flash_proxy function callProperty(name:*, ... args):* { var err:Boolean = false; if ( args.length == 0 || args.length > 4 ) err = true; if ( !( args[0] is Function ) ) err = true; if ( args.length > 1 && !(args[1] is Boolean ) ) err = true; if ( args.length > 2 && !(args[2] is int ) ) err = true; if ( args.length == 4 && !(args[3] is Boolean ) ) err = true; if( err ) { throw new Error( "usage: eventName(handler:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false)" ); } args.unshift( String(name) ); addEventListener.apply( this, args ); } override flash_proxy function hasProperty(name:*):Boolean { if ( _listeners[name] ) return true; else return false; } override flash_proxy function deleteProperty( name:* ):Boolean { if ( !_listeners[name] ) return false; _remove( _listeners[name] ); return delete _listeners[name]; } override flash_proxy function getProperty( name:* ):* { if ( _listeners[name] ) return _listeners[name]; else return undefined; } override flash_proxy function setProperty( name:*, value:* ):void { if ( value is Function ) { delete this[name]; _listeners[name] = new $listener( this, name, value, _useCapture, _priority, _useWeakReference ); } else if ( value is $listener ) { delete this[name]; _listeners[name] = new $listener( this, name, value._targetHandler, value._useCapture, value._priority, value._useWeakReference ); } else if ( value is Boolean ) { if ( value ) resume( name ); else abort( name ); return; } else if ( value == null || value==undefined ) { delete this[name]; return; } else { throw new TypeError("FAdapter:type error." ); } _add( _listeners[name] ); } } } class $listener { internal var _ref:*; internal var _type:String; internal var _handler:Function; internal var _useCapture:Boolean; internal var _priority:int; internal var _useWeakReference:Boolean; internal var _active:Boolean; internal var _targetHandler:Function = null; public function $listener( ref_:*, type_:String, handler_:Function, useCapture_:Boolean, priority_:int, useWeakReference_:Boolean ) { _ref = ref_; _type = type_; _handler = handler_; _targetHandler = handler_; _useCapture = useCapture_; _priority = priority_; _useWeakReference = useWeakReference_; _active = false; } public function get type():String { return _type; } public function get handler():Function { return _targetHandler; } public function get useCapture():Boolean { return _useCapture; } public function get priority():int { return _priority; } public function get useWeakReference():Boolean { return _useWeakReference; } public function get active():Boolean { return _active; } public function toString():String { return "[$listener active=" + String(_active) + " type=" + _type + " handler=" + String(_targetHandler) + " useCapture=" + String(_useCapture) + " priority=" + String(_priority) + " useWeakReference=" + String(_useWeakReference) + " ]"; } }