/ Published in: ActionScript 3
Expand |
Embed | Plain Text
Copy this code and paste it in your HTML
package kc.tda { import kc.api.ICollection; import kc.api.IIterator; import kc.events.CollectionEvent; import flash.errors.IllegalOperationError; import flash.events.EventDispatcher; [Event( name="add", type="kc.events.CollectionEvent" )] [Event( name="addAll", type="kc.events.CollectionEvent" )] [Event( name="clear", type="kc.events.CollectionEvent" )] [Event( name="remove", type="kc.events.CollectionEvent" )] [Event( name="removeAll", type="kc.events.CollectionEvent" )] [Event( name="retain", type="kc.events.CollectionEvent" )] public class ArrayCollection extends EventDispatcher implements ICollection { // @const public static const DEFAULT_CAPACITY:int = 1 << 5; public static const DEFAULT_MIN_CAPACITY:int = 1 << 4; public static const DEFAULT_MAX_CAPACITY:int = 1 << 30; public static const DEFAULT_LOAD_FACTOR:Number = .75; public static const DEFAULT_MIN_LOAD_FACTOR:Number = 0; public static const DEFAULT_MAX_LOAD_FACTOR:Number = 1; public static const NOT_FOUND:int = -1; public static const MAX_DISPATCH_EVENTS:int = 255; // @protected protected var _records:Array; protected var _capacity:int; protected var _events:Array; protected var _expandableCapacity:Boolean; protected var _loadFactor:Number; protected var _maxCapacity:int; protected var _enableEvents:int; // @Cconstructor public function ArrayCollection( capacity:int = undefined, expandableCapacity:Boolean = false, loadFactor:Number = NaN ) { super(this); _events = [ CollectionEvent.ADD, CollectionEvent.ADD_ALL, CollectionEvent.CLEAR, CollectionEvent.REMOVE, CollectionEvent.REMOVE_ALL, CollectionEvent.RETAIN ]; _capacity = ResolveLimits ( capacity, DEFAULT_MIN_CAPACITY, DEFAULT_MAX_CAPACITY, DEFAULT_CAPACITY ); this.loadFactor = loadFactor; this.expandableCapacity = expandableCapacity; clear(); } // @override override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void { ThrowEventsFilter( type ); super.addEventListener( type, listener, useCapture, priority, useWeakReference ); } // @properties (rw) public function get eventsReleased():int { return _enableEvents; } public function get enableEvents():Boolean { return ( _enableEvents > NOT_FOUND ); } public function set enableEvents( value:Boolean ):void { _enableEvents = ( ! value ) ? NOT_FOUND : 0; } public function get expandableCapacity():Boolean { return _expandableCapacity; } public function set expandableCapacity( value:Boolean ):void { _expandableCapacity = value; } public function get loadFactor():Number { return _loadFactor; } public function set loadFactor( value:Number ):void { _loadFactor = ResolveLimits ( value, DEFAULT_MIN_LOAD_FACTOR, DEFAULT_MAX_LOAD_FACTOR, DEFAULT_LOAD_FACTOR ); } // @methods public function add( value:* ):Boolean { if( ! ResolveStatus() ) { return false; } var quantity:int = size(); _records.push( value ); if( size() != quantity ){ ResolveDispatchEvent( CollectionEvent.ADD ); return true; } return false; } public function addAll( value:ICollection ):Boolean { var i:IIterator = value.iterator(); var quantity:int = size(); enableEvents = false; while( i.hasNext() ){ add( i.next() ); } enableEvents = true; if( size() != quantity ){ ResolveDispatchEvent( CollectionEvent.ADD_ALL ); return true; } return false; } public function availableCapacity():int { return ( _maxCapacity - size() ); } public function capacity():int { return _maxCapacity; } public function clear():void { if( _records != null ) { ResolveDispatchEvent( CollectionEvent.CLEAR ); } _records = new Array(); _maxCapacity = _capacity; } public function compare( value1:*, value2:* ):int { ThrowMethodIsNotAvailable( "compare" ); return NOT_FOUND; } public function compareTo( value:* ):int { ThrowIsNotCollection( value ); if( size() > value.size() ) return 1; else if( size() < value.size() ) return -1; else return 0; } public function contains( value:* ):int { return _records.indexOf( value ); } public function containsAll( value:ICollection ):Boolean { var i:IIterator = value.iterator(); while( i.hasNext() ){ if( contains( i.next() ) == NOT_FOUND ) { return false; } } return true; } public function copy():ICollection { var collection:ArrayCollection = new ArrayCollection( _capacity, _expandableCapacity, _loadFactor ); collection.addAll( this ); return collection; } public function equals( value:* ):Boolean { return ( this == value ); } public function isEmpty():Boolean { return ( size() == 0 ); } public function iteratorWithCopy():IIterator { return new ArrayIterator( toArray() ); } public function iterator():IIterator { return new ArrayIterator( _records ); } public function remove( value:* ):Boolean { ThrowIsEmpty(); var index:int = contains( value ); if( index != NOT_FOUND ) { if( _records.splice( index, 1 ).length ){ ResolveDispatchEvent( CollectionEvent.REMOVE ); return true; } } return false; } public function removeAll( value:ICollection ):Boolean { var i:IIterator = value.iterator(); var quantity:int = size(); enableEvents = false; while( i.hasNext() ){ remove( i.next() ); } enableEvents = true; if( size() != quantity ){ ResolveDispatchEvent( CollectionEvent.REMOVE_ALL ); return true; } return false; } public function retainAll( value:ICollection ):Boolean { var i:IIterator = iterator(); var quantity:int = size(); enableEvents = false; while( i.hasNext() ){ if( value.contains( i.next() ) == NOT_FOUND ) { i.remove(); } } enableEvents = true; if( size() != quantity ){ ResolveDispatchEvent( CollectionEvent.RETAIN ); return true; } return false; } public function size():uint { return _records.length; } public function toArray():Array { return _records.slice(); } public function threshold():int { return ( _maxCapacity * _loadFactor ); } // @purge public function purge(...rest):void { _records = null; _events = null; _capacity = undefined; _expandableCapacity = undefined; _loadFactor = undefined; _maxCapacity = undefined; _enableEvents = undefined; } // @helpres protected function ResolveDispatchEvent( value:String ):void { if( ! enableEvents || _enableEvents == MAX_DISPATCH_EVENTS ) { enableEvents = false; return; }else if( dispatchEvent( new CollectionEvent( value ) ) ) { _enableEvents++; } } protected function ResolveLimits( value:Number, min:Number, max:Number, def:Number = undefined ):Number { return Math.min ( max, Math.max ( min, value ) ) || def; } protected function ResolveLimitsAndCapacity( value:Number, min:Number, max:Number, def:Number = undefined ):Number { return ResolveCapacity ( ResolveLimits( value, min, max, def ) ); } protected function ResolveCapacity( value:int ):int { if ( ! ( value > 0 && ( ( value & ( value - 1 ) ) == 0 ) ) ) { var capacity:int = 1; while( capacity < value ) { capacity <<= 1; } return capacity; } return value; } protected function ResolveStatus():Boolean { if( ! _expandableCapacity && availableCapacity() == 0 ) { return false; } ResolveResize(); return true; } protected function ResolveResize():void { if( _expandableCapacity && size() == threshold() ) { _maxCapacity += capacity(); } } protected function ThrowIsNotExpandibled( type:String = "collection" ):void { if( ! _expandableCapacity ) { throw new IllegalOperationError("The \"" + type + "\" is not expandibled."); } } protected function ThrowIsNotCollection( value:*, param:String = "value" ):void { if( ! value is ICollection ) { throw new IllegalOperationError("The \"" + param + "\" is not an ICollection."); } } protected function ThrowIsEmpty( type:String = "collection" ):void { if ( isEmpty() ) { throw new IllegalOperationError( "The " + type + " is empty." ); } } protected function ThrowMethodIsNotAvailable( value:String, replace:String = null ):void { var error:String = "The \"" + value + "\" method is not available."; if ( replace != null ) { error = error.substr( 0, -1 ) + ", use the \"" + replace + "\" method."; } throw new IllegalOperationError( error ); } protected function ThrowEventsFilter( value:String, list:Array = null ):void { if( ! enableEvents ){ throw new IllegalOperationError( "The events are not available." ); } if( list == null ) { list = _events; } if( list.indexOf( value ) == NOT_FOUND ) { throw new IllegalOperationError( "The event \"" + value + "\" is not available." ); } } } } // @INTERFACES package kc.api { import flash.events.IEventDispatcher; public interface ICollection extends IEventDispatcher, IIterable, IComparable, IComparator, IPurger { // @properties (rw) function get enableEvents():Boolean; function set enableEvents( value:Boolean ):void; function get expandableCapacity():Boolean; function set expandableCapacity( value:Boolean ):void; function get loadFactor():Number; function set loadFactor( value:Number ):void; // @properties (r) function get eventsReleased():int; // @methods function add( value:* ):Boolean; function addAll( value:ICollection ):Boolean; function availableCapacity():int; function capacity():int; function clear():void; function contains( value:* ):int; function containsAll( value:ICollection ):Boolean; function copy():ICollection; function isEmpty():Boolean; function remove( value:* ):Boolean; function removeAll( value:ICollection ):Boolean; function retainAll( value:ICollection ):Boolean; function size():uint; function toArray():Array; function threshold():int; } } package kc.api { public interface IComparable { // @methods function compareTo( value:* ):int; } } package kc.api { public interface IComparator { // @methods function compare( value1:*, value2:* ):int; function equals( value:* ):Boolean; } } package kc.api { public interface IIterable { // @methods function iterator():IIterator; } } package kc.api { public interface IIterator { // @methods function hasNext():Boolean; function next():*; function remove():void; function index():int; function value():*; function size():int; } } // @EVENTS package kc.events { import flash.events.Event; public class CollectionEvent extends Event { // @const public static const ADD:String = "add"; public static const ADD_ALL:String = "addAll"; public static const REMOVE:String = "remove"; public static const REMOVE_ALL:String = "removeAll"; public static const RETAIN:String = "retain"; public static const CLEAR:String = "clear"; // @queue public static const ENQUEUE:String = "enqueue"; public static const DEQUEUE:String = "dequeue"; // @stack public static const PUSH:String = "push"; public static const POP:String = "pop"; // @history public static const INDEX_CHANGE:String = "indexChange"; // @constructor public function CollectionEvent( type:String, bubbles:Boolean=false, cancelable:Boolean=false ) { super( type, bubbles, cancelable ); } // @override override public function clone():Event { return new CollectionEvent( this.type, this.bubbles, this.cancelable ); } override public function toString():String { return this.formatToString( "CollectionEvent", "type", "bubbles", "cancelable", "eventPhase" ); } } }
URL: http://www.kirikacode.com