package org.libspark.model { import flash.events.Event; import flash.utils.Dictionary; import org.libspark.collection.array.ArrayedArray; import org.libspark.common.ability.ICopyable; import org.libspark.common.store.IReadableStore; import org.libspark.common.store.IWritableStore; import org.libspark.events.CollectionChangeEvent; import org.libspark.events.HierarchicalEventDispatcher; import org.libspark.events.IHierarchicalEventDispatcher; import org.libspark.events.ModelEvent; public class ArrayModel extends ArrayedArray implements IModel { public static function makeEmpty():ArrayModel { return new ArrayModel(); } public static function fromArray(source:Array, copy:Boolean = false):ArrayModel { return new ArrayModel(source, copy); } public function ArrayModel(source:Array = null, copy:Boolean = false) { super(source, copy); dispatcher = new HierarchicalEventDispatcher(this); } protected function addDependency(model:IModel):void { if (model.parentDispatcher == null) { model.parentDispatcher = this; } } protected function removeDependency(model:IModel):void { if (model.parentDispatcher == this) { model.parentDispatcher = null; } } override public function add(item:Object):void { super.add(item); if (item is IModel) { addDependency(item as IModel); } var indexes:ArrayedArray = new ArrayedArray([endIndex]); var newItems:ArrayedArray = new ArrayedArray([item]); dispatchEvent(new CollectionChangeEvent(CollectionChangeEvent.ADD, indexes, newItems)); dispatchEvent(new ModelEvent(ModelEvent.UPDATE)); } override public function insert(item:Object, index:int):void { super.insert(item, index); if (item is IModel) { addDependency(item as IModel); } var indexes:ArrayedArray = new ArrayedArray([index]); var newItems:ArrayedArray = new ArrayedArray([item]); dispatchEvent(new CollectionChangeEvent(CollectionChangeEvent.ADD, indexes, newItems)); dispatchEvent(new ModelEvent(ModelEvent.UPDATE)); } override public function replace(item:Object, index:int):void { var oldItem:Object = itemAt(index); if (oldItem is IModel) { removeDependency(oldItem as IModel); } super.replace(item, index); if (item is IModel) { addDependency(item as IModel); } var indexes:ArrayedArray = new ArrayedArray([index]); var newItems:ArrayedArray = new ArrayedArray([item]); var oldItems:ArrayedArray = new ArrayedArray([oldItem]); dispatchEvent(new CollectionChangeEvent(CollectionChangeEvent.REPLACE, indexes, newItems, oldItems)); dispatchEvent(new ModelEvent(ModelEvent.UPDATE)); } override public function swap(indexA:int, indexB:int):void { var oldItemA:Object = itemAt(indexA); var oldItemB:Object = itemAt(indexB); super.swap(indexA, indexB); var newItemA:Object = itemAt(indexA); var newItemB:Object = itemAt(indexB); var indexes:ArrayedArray = new ArrayedArray([indexA, indexB]); var newItems:ArrayedArray = new ArrayedArray([newItemA, newItemB]); var oldItems:ArrayedArray = new ArrayedArray([oldItemA, oldItemB]); dispatchEvent(new CollectionChangeEvent(CollectionChangeEvent.SWAP, indexes, newItems, oldItems)); dispatchEvent(new ModelEvent(ModelEvent.UPDATE)); } override public function removeAt(index:int):void { var oldItem:Object = itemAt(index); if (oldItem is IModel) { removeDependency(oldItem as IModel); } super.removeAt(index); var indexes:ArrayedArray = new ArrayedArray([index]); var oldItems:ArrayedArray = new ArrayedArray([oldItem]); dispatchEvent(new CollectionChangeEvent(CollectionChangeEvent.REMOVE, indexes, null, oldItems)); dispatchEvent(new ModelEvent(ModelEvent.UPDATE)); } public function sortOn(key:String = null, option:uint = 0):void { var indices:Array = null; if (key == null ) { indices = array.sort(option | Array.RETURNINDEXEDARRAY); } else { indices = array.sortOn(key, option | Array.RETURNINDEXEDARRAY); } var indexMap:Dictionary = new Dictionary(); var l:uint = indices.length; for (var i:uint = 0; i < l; ++i) { var index:uint = indices[i]; while (indexMap[index] != null) { index = indexMap[index]; } swap(i, index); indexMap[i] = index; } } public function merge(other:ArrayModel):void { var old:ArrayedArray = new ArrayedArray(array.concat()); old.useEqualityComparsion = useEqualityComparsion; var l:uint = other.count; for (var i:uint = 0; i < l; ++i) { var item:Object = other.itemAt(i); var index:int = indexOf(item); if (index != -1) { var oldItem:ICopyable = itemAt(index) as ICopyable; if (oldItem != null) { oldItem.copy(item as ICopyable); } swap(index, i); old.remove(item); } else { insert(item, i); } } l = old.count; for (i = 0; i < l; ++i) { remove(old.itemAt(i)); } } private var _dispatcher:IHierarchicalEventDispatcher; protected function get dispatcher():IHierarchicalEventDispatcher { return _dispatcher; } protected function set dispatcher(value:IHierarchicalEventDispatcher):void { _dispatcher = value; } public function get parentDispatcher():IHierarchicalEventDispatcher { return dispatcher.parentDispatcher; } public function set parentDispatcher(value:IHierarchicalEventDispatcher):void { dispatcher.parentDispatcher = value; } public function dispatchCaptureEvent(event:Event):void { dispatcher.dispatchCaptureEvent(event); } public function dispatchBubblingEvent(event:Event):void { dispatcher.dispatchBubblingEvent(event); } public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void { dispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference); } public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void { dispatcher.removeEventListener(type, listener, useCapture); } public function dispatchEvent(event:Event):Boolean { return dispatcher.dispatchEvent(event); } public function hasEventListener(type:String):Boolean { return dispatcher.hasEventListener(type); } public function willTrigger(type:String):Boolean { return dispatcher.willTrigger(type); } } }