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

📄 randomwalk.as

📁 QS我也没用过
💻 AS
📖 第 1 页 / 共 3 页
字号:
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

	import mx.managers.HistoryManager;
	import mx.managers.IHistoryManagerClient;
	import flash.events.Event;

	/*	The styles this component will support.  By declaring them here, in metadata, the MXML compiler will allow developers to define inline styles on
	*	MXML tags, and perform property type checking.  Styles should be declared using the camelCase notation
	*	In general, you shouldn't declare styles as inheriting. Inheriting styles are applied globally in Flex, so if you declare a style
	*	as inheriting, it may accidentally cascade down to a subcomponent that uses the same style name for a different meaning. Use
	*	other techniques to intentionally propogate style values from components to internal sub-components */
	[Style(name="horizontalGap", type="Number", format="Length", inherit="no")]
	[Style(name="verticalGap", type="Number", format="Length", inherit="no")]

	/*  A skin is really just another style as far as the Flex compiler is concerned. by defining the style as type Class, you can use either the Embed() 
	*	or ClassReference() CSS functions to name either a bitmap or programmatic skin via CSS.
	*/
	[Style(name="itemHighlightSkin", type="Class", inherit="no")]

	/*  Styles used by the default programmatic highlightSkin 
	*/
	[Style(name="highlightRadius", type="Number", inherit="no")]
	[Style(name="highlightColors", type="Array", inherit="no")]

	/*  The events this component will dispatch. By declaring them here, in metadata, the MXML compiler will allow developers to attach an event handler in MXML.
	*	otherwise it would see the handler as an attempt to set a non-existant property */	
	[Event(name="itemClick", type="randomWalkClasses.RandomWalkEvent")]	

	/* 	This component's default property. Declaring a default property allows the developer to specify the value of the property
	*	as the content of its tag in MXML without having to explicitly wrap it in a property tag.  Be judicious with your use of this
	*	feature...only use it in scenarios where a developer might reasonably consider the value of this property to be the 'content' 
	*	or intrinsic value of the component.  We consider it best practice not to declare scalar values properties (numbers, strings)
	*	as default properties as these are generally best specified as attributes
	*/
	[DefaultProperty("dataProvider")]
		
	/* 	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 RandomWalk extends UIComponent implements IFocusManagerComponent,
		IHistoryManagerClient
	{
		/* private variables of the component */
		private var _dataProvider:XML;
		private var _nodesInvalid:Boolean = true;
		private var _renderers:Array = [];
		private var _selectedPathIndices:Array = [];
		private var _itemRenderer:IFactory = new ClassFactory(RandomWalkRenderer);
		private var _rendererDataMap:Object;
		private var _dataRendererMap:Object;
		private var _highlightedNode:XML;
		private var _highlight:IFlexDisplayObject;
		private var _background:IFlexDisplayObject;
		private var _lineSprite:Sprite;
		private var _historyManagementEnabled:Boolean = false;
		
		
		/* 	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;
		
		/* 	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 RandomWalk()
		{
			super();
			_rendererDataMap = {};
			_dataRendererMap = {};
			
			addEventListener(Event.ADDED, addedHandler);
			addEventListener(Event.REMOVED, removedHandler);

		}
		
		override protected function createChildren():void
		{
			super.createChildren();
			
			var backgroundClass:Class = getStyle("backgroundSkin");
			if (backgroundClass != null)
			{
				_background = new backgroundClass()
				if(_background is ISimpleStyleClient)
					ISimpleStyleClient(_background).styleName = this;
				addChild(DisplayObject(_background));
			}
			var highlightClass:Class = getStyle("itemHighlightSkin");
			if (highlightClass != null)
			{
				_highlight = new highlightClass();
				if(_highlight is ISimpleStyleClient)
					ISimpleStyleClient(_highlight).styleName = this;
				addChild(DisplayObject(_highlight));
			}
			_lineSprite = new Sprite();
			addChild(_lineSprite);
		}
		
		/*  ----------------------------------------------------------------------------------------
		/ public properties
		*/

		public function set dataProvider(value:XML):void
		{
			_dataProvider = value;
			_nodesInvalid = true;
			invalidateProperties();
		}

		[Bindable] public function get dataProvider():XML
		{
			return _dataProvider;
		}
		
		public function set itemRenderer(value:IFactory):void
		{
			_itemRenderer = value;
			for (var i:int = 0;i<_renderers.length;i++)
				removeInstances(_renderers[i]);
			_renderers = [];
			invalidateProperties();				
		}
		
		[Bindable] public function get itemRenderer():IFactory
		{
			return _itemRenderer;
		}

		
		public function set historyManagementEnabled(value:Boolean):void
		{
			if (_historyManagementEnabled != value)
			{
				_historyManagementEnabled = value;
				if (_historyManagementEnabled)
					HistoryManager.register(this);
				else
					HistoryManager.unregister(this);
			}
		}

		[Bindable] public function get historyManagementEnabled():Boolean
		{
			return _historyManagementEnabled;
		}

		/*  ----------------------------------------------------------------------------------------
		/ 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:UIComponent;
			var j:int;
			var i:int;
			
			if(_nodesInvalid)
			{
				_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;
						_dataRendererMap[UIDUtil.getUID(childNode)] = inst;
						
						// 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.
						IDataRenderer(inst).data = childNode;
						
						// it's often the case that a component will have more information its item renderers might be interested in than just the data.  It's the practice
						// in Flex to define a separate interface to allow define the additional information your component might pass to an item renderer.  Try not to require
						// that your item renderers implement this interface...it's nice to provide customers with the option to invest less effort but still get a gracefully
						// degrading experience.
						
						// in this case, we think our item renderers might want to render differently based on whether they're selected or not.  While in controlled situations, you
						// could just explicitly set the 'currentState' property of your renderers, If you want to allow developers to swap in different item renderers, that's not a great
						// idea. It essentially hijacks the view states of the item renderer, and doesn't allow the developer to add additional states or behavior.  Better to let them
						// manage their own currentState.
						if (inst is IRandomWalkRenderer)
							IRandomWalkRenderer(inst).selectedState = (isNaN(selectedIndex)?  NaN:
																	   (selectedIndex == j)? 	1:
																	   						 	0);
					}
					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 = _itemRenderer.newInstance();
			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;	
		}
		
		private function dataToInstance(value:XML):UIComponent
		{
			return _dataRendererMap[UIDUtil.getUID(value)];
		}

⌨️ 快捷键说明

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