Flex 对ArrayCollection的重构

由于项目的需要,对ArrayCollection进行重构,包括如下功能:
1,排序
2,moveFirst moveLast moveNext movePre 进行记录导航 和选择某个index的对象
3,删除,更新,插入,添加记录的功能
4,过滤
以下是例子:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init();">
<mx:Script>
	<![CDATA[
		import mx.collections.CursorBookmark;
		import com.hexagonstar.util.debug.Debug;
		import org.app.utils.common.collections.MyArrayCollection;
		import com.adobe.serialization.json.JSON;
		var arr:Array=[
			{a:1,b:1,c:1},
			{a:21,b:21,c:21},
			{a:12,b:12,c:12},
			{a:10,b:10,c:10},
			{a:2,b:2,c:2}
			];
		[Bindable]
		var coll:MyArrayCollection = null;
		[Bindable]
		var scc:String = null;
		private function init():void{
			coll =new MyArrayCollection(arr);
			//var sortArr:Array=[{name:"a"},{name:"b"}];
			//coll.sortCollection(sortArr);
			src.text= coll.toString();
			//dest.text = JSON.encode(coll.currentItem);
			scc = coll.toString();
			dest.text = scc;
			//keywords
			coll.keywords=["a"];
		}
		
		private function insert():void{
			var s:String = src.text;
			var o:Object = JSON.decode(s);
			coll.insertItem(o);
			scc = coll.toString();
			dest.text = scc;
		}
		private function append():void{
			var s:String = src.text;
			var o:Object = JSON.decode(s);
			coll.appendItem(o);
			scc = coll.toString();
			dest.text = scc;
		}
		private function moveFirst():void{
			var o:Object = coll.moveFirst();
			dest.text = JSON.encode(o);
		}
		private function moveLast():void{
			var o:Object = coll.moveLast();
			dest.text = JSON.encode(o);
		}
		private function moveNext():void{
			var o:Object = coll.moveNext();
			dest.text = JSON.encode(o);
		}
		private function movePre():void{
			var o:Object = coll.movePrevious();
			dest.text = JSON.encode(o);
		}
		private function doClear():void{
			dest.text = "";
		}
		private function doUpd():void{
			var o:Object = JSON.decode(src.text);
			coll.updateItem(o);
			o = coll.currentItem;
			dest.text = JSON.encode(o);
		}
		private function doDel():void{
			var o:Object = JSON.decode(src.text);
			var flg:Boolean = coll.remove();
			Debug.trace("--remove:"+flg);
			scc = coll.toString();
			dest.text = scc;
		}
	]]>
</mx:Script>
	<mx:TextArea id="src" x="25" y="40" width="267" height="103"/>
	<mx:Button x="25" y="10" label="更新" click="doUpd();"/>
	<mx:Button x="188" y="10" label="删除" click="doDel();"/>
	<mx:Button x="244" y="10" label="排序"/>
	<mx:Button x="76" y="10" label="插入" click="insert();"/>
	<mx:Button x="132" y="10" label="添加" click="append();"/>
	<mx:TextArea id="dest" x="300" y="40" width="333" height="103" editable="false" text="{scc}"/>
	<mx:Button x="25" y="299" label="|&lt;" toolTip="第一个" click="moveFirst();"/>
	<mx:Button x="125" y="299" label="&gt;&gt;" toolTip="后一个" click="moveNext();"/>
	<mx:Button x="73" y="299" label="&lt;&lt;" toolTip="前一个" click="movePre();"/>
	<mx:Button x="177" y="299" label="&gt;|" toolTip="最后一个" click="moveLast();"/>
	<mx:DataGrid x="25" y="151" width="608" height="143" dataProvider="{coll}">
		<mx:columns>
			<mx:DataGridColumn headerText="ColumnA" dataField="a"/>
			<mx:DataGridColumn headerText="ColumnB" dataField="b"/>
			<mx:DataGridColumn headerText="ColumnC" dataField="c"/>
		</mx:columns>
	</mx:DataGrid>
	<mx:Button x="585" y="10" label="清空" toggle="true" click="doClear();"/>
</mx:Application>

以下是源码:
/**
 * 用法:
 * coll=new ArrayCollection(
 * 			[
 * 			 {name: "Martin Foo", age: 25}, 
 * 			 {name: "Joe Bar", age: 15}, 
 *           {name: "John Baz", age: 23}
 *          ]
 * );
 * coll.addItemAt({name: "James Fez", age: 40}, 0);
 */
package org.app.utils.common.collections
{	
	import flash.events.Event;
	
	import mx.collections.ArrayCollection;
	import mx.collections.CursorBookmark;
	import mx.collections.IViewCursor;
	import mx.collections.Sort;
	import mx.collections.SortField;
	import mx.events.FlexEvent;
	import mx.logging.ILogger;
	
	import org.app.framework.AppContext;
	import org.app.utils.common.MyJSONUtils;
	import org.app.utils.log.MyLoggerManager;

	public class MyArrayCollection extends ArrayCollection
	{
		////////////////////////////////////////////////////////////////////////
		/*排序规则参数*/
		public static const RL_NAME:String = "name";//要排序的字段的名称。[String]
		public static const RL_CASEINSENSITIVE:String = "caseInsensitive";//Boolean 指定此字段的排序是否应不区分大小写。
		public static const RL_DESCENDING:String = "descending";//Boolean 指定此字段是否应按降序排序。
		/*事件相关*/
		//光标位置更新时的事件
		public static const EVENT_CURSOR_UPDATE:String = "event_cursor_update";
		/*Object 指定当要进行排序的字段包含数值 (number/int/uint) 
		 * 或数值的字符串表示形式时,比较运算符是否使用数值比较。*/
		public static const RL_NUMERIC:String = "numeric";
		////////////////////////////////////////////////////////////////////////
		private var logger:ILogger = MyLoggerManager.getLogger("MyArrayCollection",AppContext.getInstance().appLogTarget);
		////////////////////////////////////////////////////////////////////////
		/*游标*/
		private var _cursor:IViewCursor = null;//当前游标
		private var _currentItem:Object = null;//当前游标指向对象
		/*如果是JSON对象,那么有keys*/
		private var _keys:Array = null;//该数组包含的json properties
		private var _keywords:Array = null;//哪些properties是主键,用于判断重复
		public function MyArrayCollection(source:Array=null)
		{
			super(source);
			//取得当前的光标对象
			this._cursor = this.createCursor();
			//注册光标位置更新事件
			this._cursor.addEventListener(FlexEvent.CURSOR_UPDATE,fireCursorUpdate,false,0,true);
			//給当前光标对象赋值--就会触发cursor update事件
			this._cursor.seek(CursorBookmark.CURRENT);
			//初始化keys 或者 获取keys
			this.fetchKeys();
		}
		
		////////////////////////////////////////////////////////////////////////
		/**
		 * 当光标位置更新时触发的事件,在这取得当前光标位置的值,
		 * 其他地方光标移动时不要給 currentItem赋值了。
		 * @param FlexEvent
		 * @return
		 */
		private function fireCursorUpdate(event:FlexEvent):void{
			//取得当前的值
			this._currentItem = (event.currentTarget as IViewCursor).current;
			//防止 moveLast moveFirst抛出多2个事件,只有当前有对象值了,才抛出
			var a:String = "不抛出";
			if (this._currentItem) {
				a="抛出";
				this.dispatchEvent(new Event(EVENT_CURSOR_UPDATE));
			}
			var s:String = MyJSONUtils.encode(this._currentItem);
			logger.debug("--触发了 cursor update 事件,当前对象:"+s+"["+a+"]");
		}
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		public function set cursor(cursor:IViewCursor):void{
			this._cursor = cursor;
		}
		public function get cursor():IViewCursor{
			return this._cursor;
		}
		public function set currentItem(o:Object):void{
			//替换掉当前对象里面的值
			this.updateItem(o);
			//this._currentItem = o;
		}
		public function get currentItem():Object{
			return this._currentItem;
		}
		////////////////////////////////////////////////////////////////////////
		public function fetchKeys():void{
			if(this.length>0){
				var o:Object = this.getItemAt(0);
				this._keys = MyJSONUtils.fetchKeys(o);
			}else{
				this._keys = [];
			}
		}
		public function getKeys():Array{
			if(this._keys.length<=0){
				this.fetchKeys();
			}
			return this._keys;
		}
		public function set keywords(k:Array):void{
			this._keywords = k;
		}
		public function get keywords():Array{
			return this._keywords;
		}
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		
		/**
		 * 检查是否存在某个条件的对象??????
		 * @param Object  json object eg:{name:"xxx_name", age:34 .....}
		 * @param String 比较类型 采用Sort里面引用的常量
		 * @return int 存在的个数
		 * 
		 * @see mx.collections.Sort
		 */
		public function checkExist(conditionObj:Object,mode:String=Sort.ANY_INDEX_MODE):int{
			var sort:Sort = new Sort();
			return sort.findItem(this.source,conditionObj,mode);   
		}
		
		/**
		 * [这个比较 很慢]
		 * 检查是否存在某个对象,其中keys指根据哪些key进行比较,如果为空,那么根据全部key来比
		 * @param Object
		 * @param Array 要比较的key
		 * @return Boolean true存在
		 */
		public function isExist(o:Object,keys:Array=null):Boolean{
			var key1:Array = keys;
			if(key1==null){
				key1 = MyJSONUtils.fetchKeys(o);
			}
			var item1:String = null;
			var l:int=key1.length;
			for each(var obj:Object in this){
				var flg:int = 0;
				for(var i:int=0;i<l;i++){
					item1=key1[i];
					if(o[item1]==obj[item1]){
						flg++;
					}
				}
				if(flg==l)return true;
			}
			return false;
		}
		/**
		 * 覆盖该方法,来做重复检查
		 * @param Object 要比较的对象
		 * @return Boolean true存在
		 */
		override public function contains(item:Object):Boolean{
			return isExist(item,this._keywords);
		}
		////////////////////////////////////////////////////////////////////////
		/**
		 * 按照一定的规则排序,可以多个字段同时排序:
		 * -- name : String 要排序的字段的名称。 
		 * -- caseInsensitive : Boolean 指定此字段的排序是否应不区分大小写。 
		 * -- descending : Boolean 指定此字段是否应按降序排序。
		 * -- numeric : Object 指定当要进行排序的字段包含数值 (number/int/uint) 
		 *              或数值的字符串表示形式时,比较运算符是否使用数值比较。 
		 * eg:[{name:'age',caseInsensitive:true,descending:false,numeric:null},
		 *                   {name:'age',descending:false}...]
		 *   是个数组,而且 里面是json对象,包含四个元素:name,caseInsensitive,descending,numeric,
		 *   其中,name是必须的,其他的可选。
		 * @param Object 类似上面的写
		 * @return
		 * @see mx.colloections.SortField
		 * 
		 */
		public function sortCollection(conditionObj:Array):void{
			var leng:int = conditionObj.length;
			var fields:Array = [];
			var sortField:SortField = null;
			var o:Object=null;
			
			var name:String=null;
			var caseInsensitive:Boolean=false;
			var descending:Boolean = false;
			var numeric:Object = null;
			for(var i:int=0;i<leng;i++){
				o = conditionObj[i];
				sortField = new SortField();
				//加入参数
				sortField.name=o[MyArrayCollection.RL_NAME];
				
				var tmp:Object = o[MyArrayCollection.RL_CASEINSENSITIVE];
				caseInsensitive=tmp==null?false:true;
				sortField.caseInsensitive=caseInsensitive;
				
				tmp = o[MyArrayCollection.RL_DESCENDING];
				descending=tmp==null?false:true;
				sortField.descending=descending;
				
				tmp = o[MyArrayCollection.RL_NUMERIC];
				numeric=tmp==null?null:tmp;
				sortField.numeric=numeric;
				//加入比较器
				fields.push(sortField);
			}
			var sort:Sort = new Sort();
			sort.fields=fields;
			this.sort = sort;
			this.refresh();
		}
		////////////////////////////////////////////////////////////////////////
		/**
		 * 过滤,首先必须知道自己要过滤的集合里面有些什么字段,
		 * coll = new ArrayCollection([
		 *                      {name:"Martin Foo", age:25},      
         *                      {name:"Joe Bar", age:15},      
         *                      {name:"John Baz", age:23},      
         *                      {name:"Matt Baz", age:21}]);
         * 那么func:
         * private function filterFunc(value:Object):Object {      
         *  if(Number(value.age) > 21) {      
        *    return true;      
         *  }
         *  return false;      
         *} 
         * @param Function 如上
         * @return
		 */
		public function filterCollection(filterFunc:Function):void{
			this.filterFunction = filterFunc;
			this.refresh();
		}
		////////////////////////////////////////////////////////////////////////
		
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		/**
		 * 取得第一个对象,根据cursorMove 来判断是否移动光标
		 * @param Boolean 是否移动当前光标
		 * @return Object 第一个位置的对象
		 */
		public function firstItem(cursorMove:Boolean=true):Object{
			if(cursorMove){
				return this.moveFirst();
			}
			return this.getItemAt(0);
		}
		/**
		 * 取得最后一个对象,根据cursorMove 来判断是否移动光标
		 * @param Boolean 是否移动当前光标
		 * @return Object 最后一个位置的对象
		 */
		public function lastItem(cursorMove:Boolean=true):Object{
			if(cursorMove){
				return this.moveLast();
			}
			return this.getItemAt(this.length-1);
		}
		/**
		 * 在最后位置插入对象,会检查是否存在相同的对象.
		 * @param Object
		 * @return Boolean true成功 false失败
		 */
		public function appendItem(o:Object):Boolean{
			//该方法检查每个元素都相同
			var exist:Boolean= this.contains(o);
			if(!exist){
				this.addItem(o);
				//当前游标处理
				this.moveCursorTo(o);
				if(this._currentItem){
					return true;
				}
			}
			return false;
		}
		
		/**
		 * 在当前位置插入一个对象
		 * @param Object 
		 * @return Boolean
		 */
		public function insertItem(o:Object):Boolean{
			//该方法检查每个元素都相同
			var exist:Boolean= this.contains(o);
			if(!exist){
				this._cursor.insert(o);
				//当前游标处理
				this.moveCursorTo(o);
				if(this._currentItem){
					return true;
				}
			}
			return false;
		}
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		/**
		 * 删除当前光标指向的对象,并选择下一个对象,如果下一个对象为空,那么选择最后一个
		 * @return Object 当前被删除的对象
		 * 
		 */
		public function remove():Object {
			var o:Object=this._cursor.remove();
			if (!this._currentItem) {
				this._cursor.movePrevious();
			}
			return o;
		}
		/**
		 * 删除指定的对象
		 * @param Object
		 * @return Boolean true成功 
		 */
		public function removeItem(o:Object):Boolean{
			this.moveCursorTo(o);
			var o:Object = this.remove();
			if(o)return true;
			return false;
		}
		
		/**
		 * 删除所有数据
		 */
		override public function removeAll():void{
			super.removeAll();
			this.source = [];
		}
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		/**
		 * 更新当前光标指向的对象
		 * @param Object 新的对象
		 * @return
		 */
		public function updateItem(o:Object):void{
			var keys:Array = MyJSONUtils.fetchKeys(o);
			var l:int = keys.length;
			var key:String=null;
			for(var i:int=0;i<l;i++){
				key = keys[i];
				if(this._currentItem[key]){
					this._currentItem[key]=o[key];
					this.itemUpdated(this._currentItem);//这个会令ui更新
				}
			}
		}
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		/**
		 * 把光标移到指定的对象上,
		 * @param Object 目标对象
		 * @return Object 当前选择的对象
		 */
		public function moveCursorTo(o:Object):Object {
			//当前游标处理
			var index:int=this.getItemIndex(o);
			return this.moveCursorByIndex(index);
		}
		public function moveCursorByIndex(index:int):Object{
			if(index < 0 || index >= this.length)return null;
			var oldIndex:int = this.getItemIndex(this._currentItem);
			var offset:int = 0;
			if (oldIndex > index) {
				offset = -(oldIndex - index);
			} else if (oldIndex < index) {
				offset = index - oldIndex;
			}
			this._cursor.seek(this._cursor.bookmark, offset);
			return this._currentItem;
		}
		
		/**
		 * 光标指向第一个位置,返回第一个位置的值 
		 * @return Object 当前光标位置的对象
		 */
		public function moveFirst():Object{
			//当前游标处理
			this._cursor.seek(CursorBookmark.FIRST);
			//当前对象设置值
			//在cursor update 事件里面处理了
			//返回当前对象
			return this._currentItem;
		}
		
		/**
		 * 光标指向最后一个位置,返回最后一个位置的值 
		 * @return Object 当前光标位置的对象
		 */
		public function moveLast():Object{
			//当前游标处理
			this._cursor.seek(CursorBookmark.LAST);
			//当前对象设置值
			//在cursor update 事件里面处理了
			//返回当前对象
			return this._currentItem;
		}
		
		/**
		 * 光标指向下一个位置,返回光标指向位置的对象
		 * @return Object 当前光标位置的对象
		 */
		public function moveNext():Object {
			if (!this._cursor.afterLast) {
				this._cursor.moveNext();
				//this._currentItem = this._cursor.current;
				if (!this._currentItem) {
					this._cursor.movePrevious();
				}
			}
			return this._currentItem;
		}
		
		/**
		 * 光标指向上一个位置,返回光标指向位置的对象
		 * @return Object 当前光标位置的对象
		 */
		public function movePrevious():Object {
			if (!this._cursor.beforeFirst) {
				this._cursor.movePrevious();
				if (!this._currentItem) {
					this._cursor.moveNext();
				}
			}
			return this._currentItem;
		}
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		/**
		 * 把值转成字符串
		 * @return String 
		 */
		override public function toString():String{
			var s:String = "";
			var l:int=this.length;
			for(var i:int=0;i<l;i++){
				s+=MyJSONUtils.encode(this.getItemAt(i));
			}
			return s;
		}
		
		
	}//end class
}//end package

你可能感兴趣的:(C++,c,json,Flex,C#)