⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simplerandomwalk.as

📁 QS我也没用过
💻 AS
📖 第 1 页 / 共 2 页
字号:
package
{
	import mx.core.UIComponent;
	import mx.core.ClassFactory;
	import mx.controls.Label;
	import flash.utils.Dictionary;
	import mx.core.IDataRenderer;
	import flash.events.MouseEvent;
	import mx.utils.UIDUtil;
	import mx.core.IFactory;
	import randomWalkClasses.RandomWalkEvent;
	import mx.core.IFlexDisplayObject;
	import flash.display.DisplayObject;
	import mx.styles.ISimpleStyleClient;
	import mx.skins.RectangularBorder;
	import randomWalkClasses.RandomWalkRenderer;
	import randomWalkClasses.IRandomWalkRenderer;
	import flash.display.Sprite;

	import flash.events.KeyboardEvent;
	import flash.ui.Keyboard;
	import mx.managers.IFocusManagerComponent

	/* 	RandomWalk extends UIComponent. The first decision you have to make when building a custom component is what 
	*	base class to use.  While a container class is a natural inclination, it is not always the best choice. Use a container
	*	class if you want its benefits -- built in scroll functionality, and the ability to easily declare and manage children from MXML.
	*	If instead you are creating a component that will feel more like a control to the developer -- i.e., one that is used to represent
	*	data, or an actionable task for the user, rather than to group and manage other components -- consider using UIComponent. 
	*	UIComponent can contain other controls (and raw flash display objects) to achieve whatever rendering and interaction behaviors
	*	it requires
	*/
	public class SimpleRandomWalk extends UIComponent
	{
		/* private variables of the component */
		private var _dataProvider:XML;
		private var _nodesInvalid:Boolean = true;
		private var _renderers:Array = [];
		private var _selectedPathIndices:Array = [];
		private var _rendererDataMap:Object;
		private var _highlightedInstance:UIComponent;
		protected var _lineSprite:Sprite;
		
		/* 	private constants. In the process of developing a component, a constant used in the rendering of the component
		*	is often a good candidate for something that should be a style configurable by the developer via CSS.
		*/
		private const GAP_FROM_LEFT_RENDERER_EDGE:Number = 2;
		private const ITEM_RENDERER_INDEX:Number = 3;
		private const GAP_FROM_TOP_EDGE:Number = 2*GAP_FROM_LEFT_RENDERER_EDGE;
		private const HORIZONTAL_GAP:Number = 2;
		private const VERTICAL_GAP:Number = 2;
		
		/* 	The constructor.  Developer's often create and add internal children in their constructor, but you'll improve the initialization
		*	performance of your component if you wait to init children in your createChildren() routine.
		*/
		public function SimpleRandomWalk()
		{
			super();
			_rendererDataMap = {};

		}

		override protected function createChildren():void
		{
			super.createChildren();
			
			if(_lineSprite == null)
			{
				_lineSprite = new Sprite();
			}
			addChild(_lineSprite);
		}
		
		/*  ----------------------------------------------------------------------------------------
		/ public properties
		*/
		public function set dataProvider(value:XML):void
		{
			_dataProvider = value;
			_nodesInvalid = true;
			invalidateProperties();
		}
		public function get dataProvider():XML
		{
			return _dataProvider;
		}
		
		/*  ----------------------------------------------------------------------------------------
		/ property management, plus data -> instance renderers
		*/

		/* 	commit properties is where a component should perform any delayed tasks related to changes in either its properties or its underlying data.
		*  	measurement and layout happen elsewhere, but any other compute intensive tasks should be deferred and executed here.  For data driven components
		*	that need to manage a dynamic list of instances to rnederer the data, this is a good place to update that list
		*/
		override protected function commitProperties():void
		{
			var root:XML = _dataProvider;
			var inst:Label;
			var j:int;
			var i:int;
			
			if(_nodesInvalid == true)
			{
				_nodesInvalid = false;
				/* 	For our component, the displayed data, and hence the renderer instances we need, are dictated by the 'selected path' through our data tree. At each level in the
				*	selected path, we iterate over the children for the open node and create a renderer for them.
				*/
				
				/* for each level in the selected path*/
				for(i = 0;i<_selectedPathIndices.length+1;i++)
				{
					// grab its children
					var children:XMLList = root.children();
					// and any instances we already have defined at that level
					var instances:Array = _renderers[i];
	
					// we're going to create renderers for the children of all of our selected nodes.
					// but our last selected node might have no children. If that's the case, we'll just stop
					// here.
					if(children.length() == 0)
						break;
						
					if(instances == null)
						instances= _renderers[i] = [];
						
					// now for each level N in the selection path, instances[N] should be an array of item renderers to display its children
					// here we make sure we have the right number of instances created for that level
					if(instances.length < children.length())
					{
						for(j = instances.length;j < children.length();j++)
						{
							instances.push(createInstance());
						}
					}
					else if (instances.length > children.length())
					{
						removeInstances( instances.splice(children.length(),instances.length - children.length()) );
					}
					
					// now that we know we have enough renderers, iterate over each renderer, set its data,
					// and its selected state
					var selectedIndex:Number = _selectedPathIndices[i];
					
					for(j=0;j<children.length();j++)
					{
						var childNode:XML = children[j];
						inst = instances[j];
						// when the user clicks on a renderer, we need to know which node it corresponds to. Since AS3 doesn't allow us to decorate 
						// components with arbitrary properties, we'll use a separate HashMap to map from instances to data nodes.
						_rendererDataMap[UIDUtil.getUID(inst)] = childNode;
						
						// set the instances data.  Flex's convention is that item renderers that want to know about data implement the IDataRenderer interface.
						// if you reasonably think an item renderer that didn't know about its data would be useless in your component, feel free to just assume
						// that your renderer implements it.
						inst.text = childNode.@label;
						
					}
					if(i < _selectedPathIndices.length)
					{
						root = children[_selectedPathIndices[i]];
					}				
				}
				
				// since we've made changes that affect our size and display, we must invalidate to trigger an update.	
				invalidateSize();
				invalidateDisplayList();
			}
		}
		
		private function removeInstances(instances:Array):void
		{
			for(var i:int=0;i<instances.length;i++)
				removeChild(instances[i]);
		
		}
		private function createInstance():UIComponent
		{
			var inst:UIComponent = new Label();
			inst.addEventListener(MouseEvent.CLICK,itemClickHandler);
			inst.addEventListener(MouseEvent.ROLL_OVER,itemRollOverHandler);
			inst.addEventListener(MouseEvent.ROLL_OUT,itemRollOutHandler);			
			addChildAt(inst,Math.min(numChildren,ITEM_RENDERER_INDEX));		
			return inst;	
		}

		/*  ----------------------------------------------------------------------------------------
		/ Event handlers
		*/

		private function itemRollOverHandler(e:MouseEvent):void
		{
			_highlightedInstance = UIComponent(e.currentTarget);
			invalidateDisplayList();
		}
		private function itemRollOutHandler(e:MouseEvent):void
		{
			_highlightedInstance = null;
			invalidateDisplayList();
		}
		
		
		/* called when the user clicks on an item */
		private function itemClickHandler(e:MouseEvent):void
		{
			// currentTarget is the item we actually assigned the handler to.  Since some components have sub-pieces, target can sometimes point to 
			// a display object we know or care nothing about.
			var child:UIComponent = UIComponent(e.currentTarget);
			expandItem(child);
		}

		private function expandItem(child:UIComponent):void
		{
			// use our map to get the data associated with this item renderer
			var node:XML = _rendererDataMap[UIDUtil.getUID(child)];
			
			// first determine the node's depth
			var depth:int = 0;
			var parent:XML = node.parent();
			while(parent != null)
			{
				parent= parent.parent();
				depth++;
			}
			// now determine its index in its parent
			var idx:int = node.childIndex();
			
			// those two pieces of information allow us to update our selected path information.
			_selectedPathIndices[depth-1] = idx;
			
			// when the user clicks in the middle of the tree, we want to throw away any selected path 
			// below the one they clicked on
			_selectedPathIndices.splice(depth,_selectedPathIndices.length - (depth-1));

			// since we're potentially throwing away a part of the selected path, we want to throw away any renderers
			// we were using for that portion.
			if(_selectedPathIndices.length < _renderers.length)
			{
				var deadInstances:Array = _renderers.splice(_selectedPathIndices.length,(_renderers.length - _selectedPathIndices.length));
				for(var j:int=0;j<deadInstances.length;j++)
					removeInstances(deadInstances[j]);
			}

			
			// since our selected path changed, we'll need to update our renderers.  That's expensive, so we'll defer it until our next
			// commitProperties call.
			_nodesInvalid = true;
			invalidateProperties();						
		}
		/*  ----------------------------------------------------------------------------------------
		* 	measurement and layout
		*/

		// this is the main rendering function for the component. This function is responsible for positioning and sizing any children
		// of the component (either user specified or component generated), and doing any programmatic rendering using the drawing API.
		// the method takes two parameters, unscaledWidth and unscaledHeight. These are the assigned width and height of the component
		// in its own coordinate system (i.e., absent any scaling or rotation of the component or its parents). Generally, you want
		// to render your component relative to these values, and assume the system will take care of any other adjustments.
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			
			// If we're doing any drawing at all, we typically want to clear the graphics first thing. All drawing happens through
			// the Component's graphics objects. Forgetting to clear is a very common mistake. Because Flash is a 'retained mode' renderer, it remembers

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -