Flex Tree 之 TreeItemRenderer

package
{
	import flash.events.MouseEvent;
	import flash.xml.*;
	import mx.collections.*;
	import mx.controls.CheckBox;
	import mx.controls.Image;
	import mx.controls.Tree;
	import mx.controls.listClasses.*;
	import mx.controls.treeClasses.*;

	public class CheckTreeRenderer extends TreeItemRenderer {
        protected var myImage:Image;
        // set image properties
        private var imageWidth:Number 	= 10;
	    private var imageHeight:Number 	= 10;
        private var inner:String 	= "assets/manager.png";
		protected var myCheckBox:CheckBox;
		static private var STATE_SCHRODINGER:String = "schrodinger";
		static private var STATE_CHECKED:String = "checked";
		static private var STATE_UNCHECKED:String = "unchecked";
	    
        public function CheckTreeRenderer () {
			super();
			mouseEnabled = false;
		}
		
		/**
		 *创建组件的子对象。此方法是一种高级方法,可在创建 UIComponent 的子类时覆盖。
		 *可在自身内部创建其它组件或对象的组件称为复合组件。例如,Flex ComboBox 控件实际上包含一个 TextInput 控件(用于定义 ComboBox 的文本区域)和一个 Button 控件(用于定义 ComboBox 箭头)。
		 *组件实现 createChildren() 方法以在其内部创建子对象(如其它组件)。
		 *在 createChildren() 方法的覆盖内部,您可以调用 addChild() 方法来添加各个子对象。 
		 *您无需直接调用此方法,Flex 会调用 createChildren() 方法来响应对 addChild() 方法的调用,用以将组件添加到其父项。
		 */
		override protected function createChildren():void {
			super.createChildren();
			myCheckBox = new CheckBox();
			//垂直对齐容器中的子项。可能值包括 "top"、"middle" 和 "bottom"。默认值为 "top",
			myCheckBox.setStyle("verticalAlign", "middle");
			myCheckBox.addEventListener( MouseEvent.CLICK, checkBoxToggleHandler );
			addChild(myCheckBox);
			myImage = new Image();
	    	myImage.source = inner;
			myImage.addEventListener(MouseEvent.CLICK, imageToggleHandler);
			myImage.setStyle( "verticalAlign", "middle" );
			addChild(myImage);
	    }
	    
		/***
		 *TreeItemRenderer的data方法实现IDataRenderer 接口用于为具有 data 属性的组件定义接口。 
		 *系统使用 data 属性将要呈现或编辑的数据传递给以下组件:在 list 控件(如 List、HorizontalList、TileList、DataGrid 和 Tree 控件)中的项目渲染器或项目编辑器中使用的组件,或者用作图表中渲染器的组件。
		 *组件必须实现 IDataRenderer,以便主机组件可以传递此信息。所有 Flex 容器和许多 Flex 组件都实现 IDataRenderer 和 data 属性。
		 **/
		override public function set data(value:Object):void {
			super.data = value;
			setCheckState (myCheckBox, value, value.@state);
			if(TreeListData(super.listData).item.@type == 'dimension') {
			    setStyle("fontStyle", 'italic');
			} else {
				if (this.parent != null) {
					//指定叶项目的默认图标。在 MXML 中,可以使用以下语法设置此属性:defaultLeafIcon="@Embed(source='c.jpg');"
					Tree(this.parent.parent).setStyle("defaultLeafIcon", null);
		  		}
				setStyle("fontStyle", 'normal');
			}
	    }

		/**
		 * 绘制对象和/或设置其子项的大小和位置。此方法是一种高级方法,可在创建 UIComponent 的子类时覆盖。 
		 * 您无需直接调用此方法,使用 addChild() 方法将组件添加到容器时,以及调用组件的 invalidateDisplayList() 方法时,Flex 将调用 updateDisplayList() 方法。
		 **/
	   override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
			super.updateDisplayList(unscaledWidth, unscaledHeight);
			//super.data是为父组件提供的数据(dataProvider),根据data设置各个组件和图标的横纵坐标
	        if(super.data) {
			    if (super.icon != null) {
				    myCheckBox.x = super.icon.x;
				    myCheckBox.y = 8;
				    super.icon.x = myCheckBox.x + myCheckBox.width + 17;
				    super.label.x = super.icon.x + super.icon.width + 3;
				} else {
				    myCheckBox.x = super.label.x;
				    myCheckBox.y = 8;
				    super.label.x = myCheckBox.x + myCheckBox.width + 17;
				}
			    if (data.@state == STATE_SCHRODINGER) {
			    	myImage.x = myCheckBox.x + 3;
			    	myImage.y = myCheckBox.y + 4;
					myImage.width = imageWidth;
					myImage.height = imageHeight;
			    } else {
			    	myImage.x = 0;
			    	myImage.y = 0;
					myImage.width = 0;
					myImage.height = 0;
			    }
			}
	    }
		
		//设置父节点的状态
		private function toggleParents (item:Object, tree:Tree, state:String):void {
			if (item == null) {
				return;
			} else {
				item.@state = state;
				toggleParents(tree.getParentItem(item), tree, getState(tree, tree.getParentItem(item)));
			}
		}
		
		//设置子节点的状态
		private function toggleChildren(item:Object, tree:Tree, state:String):void	{
			if (item == null) {
				return;
			} else {
				//设置项目的选中状态
				item.@state = state;
				//ITreeDataDescriptor:提供用于对 Tree 控件显示的数据集合执行分析和添加节点操作的方法的接口。
				var treeData:ITreeDataDescriptor = tree.dataDescriptor;
				if (treeData.hasChildren(item))	{
					//ICollectionView: 是数据集合的视图。可以修改该视图以显示根据各种条件排序的数据,或显示在不修改基本数据的情况下经过滤镜筛选后的数据。
					//通过 IViewCursor,可以访问集合中的项目。可使用 IViewCursor 接口 insert() 和 remove() 方法修改该集合。 
					//getChildren :提供对子节点的访问,并返回子节点的集合视图
					var children:ICollectionView = treeData.getChildren(item);
					//IViewCursor: 定义双向枚举集合视图的接口。此光标提供查找、搜索和标记为书签的功能,还提供修改方法插入和删除。
					//首次从视图检索光标(通常使用 ICollectionViewcreateCursor() 方法)时,current 属性的值应是该视图中的第一个项目,除非视图为空。 
					var cursor:IViewCursor = children.createCursor();
					//遍历集合视图,且递归设置子节点的状态
					while (!cursor.afterLast) {
						toggleChildren(cursor.current, tree, state);
						//将光标移动到集合中的下一个项目。只有成功更新 current 属性,才能引用此新位置上的对象。如果生成的 current 属性有效,则返回 true,否则返回 false(属性值为 afterLast)。 
						cursor.moveNext();
					}
				}
			}
		}
		
		/**
		 * 获得父节点的当前状态
		 **/
		private function getState(tree:Tree, parent:Object):String {
			//选中、没选中项目的个数,和父节点图片的显示个数
			var noChecks:int = 0, noUnChecks:int = 0,noCats:int = 0;
			if (parent != null)	{
				var treeData:ITreeDataDescriptor = tree.dataDescriptor;
				var cursor:IViewCursor = treeData.getChildren(parent).createCursor();
				while (!cursor.afterLast) {
					//IViewCursor-->current(): 可以访问位于此光标引用的源集合中的位置的对象。
					if (cursor.current.@state == STATE_CHECKED)	{
						noChecks++;
					} else if (cursor.current.@state == STATE_UNCHECKED) {
						noUnChecks++
					} else {
						noCats++;
					}
					cursor.moveNext();
				}
			}
			if ((noChecks > 0 && noUnChecks > 0) || (noCats > 0)) {
				//如果有若干子节点被选中,或有图片提示,则设置图片提示
				return STATE_SCHRODINGER;
			} else if (noChecks > 0) {
				//如果所有的子节点都被选中,则父节点为选中状态
				return STATE_CHECKED;
			} else {
				//如果所有的子节点都未被选中,则父节点为未选中状态
				return STATE_UNCHECKED;
			}
		}
		
		private function imageToggleHandler(event:MouseEvent):void {
			myCheckBox.selected = !myCheckBox.selected;
			checkBoxToggleHandler(event);
		}
		
		//checkBox点击出发的事件处理函数
		private function checkBoxToggleHandler(event:MouseEvent):void {
			if (data) {
				//TreeListData 类定义 listData 属性的数据类型,此属性由 Tree 控件的嵌入式项目渲染器或嵌入式项目编辑器实现。所有嵌入式项目渲染器和嵌入式项目编辑器必须实现 IDropInListItemRenderer 接口,此接口定义了 listData 属性。 
				var myListData:TreeListData = TreeListData(this.listData);
				//被点击项目及子项目的数据(此处是xml片段)
				var selectedNode:Object = myListData.item;
				//触发事件的目标树
				var tree:Tree = Tree(myListData.owner);
				var toggle:Boolean = myCheckBox.selected;
				//根据父节点设置子节点的选中状态
				if (toggle)	{
					toggleChildren(data, tree, STATE_CHECKED);
				} else {
					toggleChildren(data, tree, STATE_UNCHECKED);
				}
				//被点击项目及父项目的数据(此处是xml片段)
				var parent:Object = tree.getParentItem(data);
				toggleParents(parent, tree, getState(tree, parent));
			}
		}
		
		/**
		 * 根据数据设置CheckBox的选中状态,在初始化和data被改变时调用
		 */
		private function setCheckState (checkBox:CheckBox, value:Object, state:String):void	{
			if (state == STATE_CHECKED)	{
				checkBox.selected = true;
			} else if (state == STATE_UNCHECKED) {
				checkBox.selected = false;
			} else if (state == STATE_SCHRODINGER) {
				checkBox.selected = false;
			}
		}	    
	}
}

xml数据:

<>
	<folder state="unchecked" label="Marketing Collateral" isBranch="true">
	      <folder state="unchecked" isBranch="true" label="Media, PR, and Communications" >
		     <folder state="unchecked" isBranch="false" label="Article Reprint Disclaimers" />
		     <folder state="unchecked" isBranch="false" label="Articles Reprints" />
		     <folder state="unchecked" isBranch="false" label="Interviews and Transcripts" />
		     <folder state="unchecked" isBranch="false" label="Press Kits" />
		     <folder state="unchecked" isBranch="false" label="Press Releases" />
		     <folder state="unchecked" isBranch="false" label="Quick Hits" />
		     <folder state="unchecked" isBranch="false" label="Rep Talking Points" />
		     <folder state="unchecked" isBranch="false" label="Special Updates" />
		     <folder state="unchecked" isBranch="false" label="White Papers" />
	      </folder>
	      <folder state="unchecked" isBranch="true" label="Forms and Applications" >
	          <folder state="unchecked" isBranch="false" label="Applications" />
	          <folder state="unchecked" isBranch="false" label="Forms" />
	      </folder>
	</folder>		
	</>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值