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

📄 randomwalk.as

📁 QS我也没用过
💻 AS
📖 第 1 页 / 共 3 页
字号:
			// Lastly, if the mouse is currently over an item, we want to provide a nice rollover effect.
			// Given that this component is using item renderers, we could just leave that as behavior the item
			// renderer should implement. But in this case, we're going to provide the functionality to save 
			// our developers the trouble.

			// First, we're not assuming the hilight exists. We could take the same tact we do with other styles and use a default if nothing is specified,
			// but we want to allow a developer to just not specify a highlight at all, so we'll guard against it here.			
			if(_highlight != null)
			{			
				if(_highlightedNode == null)
				{
					// nothing's highlighted, so we'll just hide the highlight.
					_highlight.visible = false;
				}
				else
				{
					// we've got a highlighted renderer, so position the highlight to match it.
					_highlight.visible = true;
					var highlightedInstance:UIComponent = dataToInstance(_highlightedNode);
					_highlight.move(highlightedInstance.x, highlightedInstance.y);
					_highlight.setActualSize(highlightedInstance.width,highlightedInstance.height);
				}
			}
		}

		// This internal utility function is the one that does the layout for our first pass.
		// it positions a single stack vertically and horizontally, and saves off details
		// about the dimension of the stack.
		private function renderStack(instances:Array, selectedIndex:Number, left:Number):StackDetails
		{
			var maxWidth:Number = 0;
			var top:Number = 0;
			var selectionBaseline:Number;
			var i:int;
			var verticalGap:Number = verticalGapWithDefault;
			var selectedInstance:UIComponent = null;
			
			// first, we want all of the renderers in our stack to be the same size,
			// so we're going to iterate through them and get the maximum length of 
			// the renderers.
			for(i = 0;i<instances.length;i++)
			{
				// note that we're calling the convenience function, get ExplicitOrMeasuredWidth function,
				// to decide how big these components should be.  This function returns either the explicitly assigned
				// pixel size of the component, if someone has assigned one, or its measured size otherwise. 
				// Note that if you want to support percentage based sizes in your child components, you'll need to account for
				// that separately.
				// Given that we need this information when we do measurement, if we were good developers we'd have cached it then.
				maxWidth = Math.max(maxWidth,instances[i].getExplicitOrMeasuredWidth());			
			}
			
			
			// OK, now we actually stack our components, top to bottom.
			for(i = 0;i<instances.length;i++)
			{
				// for each component
				var inst:UIComponent = instances[i];
				// getits explicit/measured sizes
				var eomHeight:Number = inst.getExplicitOrMeasuredHeight();
				var eomWidth:Number = maxWidth;
				inst.setActualSize(eomWidth,eomHeight);
				inst.move(left,top);
				// if this renderer represents a selected item, we're going to remember that, because later on we'll want
				// to store its baseline in our cached details.
				if(i == selectedIndex)
				{
					selectedInstance = inst;
					selectionBaseline = top + eomHeight;
				}
				
				// advance our marker for where the top of the next component should go.
				top += eomHeight + verticalGap;
			}

			// store off the information we've calculated that we'll be needing later.				
			var details:StackDetails = new StackDetails();
			details.top = 0;
			details.bottom = top - verticalGap;
			details.left = left;
			details.right = left + maxWidth;
			details.selectedIndex = selectedIndex;
			details.selectionBaseline = selectionBaseline;

			return details;
		}
		

		// This internal utility function does the processing for the second pass of our layout.
		// this function gets passed a stack of renderers that have already been positioned horizontally, and 
		// vertically relative to each other...a set of details describing the stack, and a target y pixel value
		// for where we want to place the baseline of the selected renderer.  This function will 
		// adjust the renderers vertically to try and match this value.
		private function alignStack(instances:Array, details:StackDetails,selectionBaselineTarget:Number):Number
		{
			// 
			var stackHeight:Number = details.bottom - details.top;
			var selectionBaseline:Number;
			var i:int;
			var inst:UIComponent;
			
			// first, grab the current position of our the baseline of our selected component.
			// this is the point in the stack that we want to move to line up with our target.
			// if we don't have a selection, then we're going to want to try and align the center
			// of the stack with the target.
			selectionBaseline = details.selectionBaseline;
			if(isNaN(selectionBaseline))
				selectionBaseline = stackHeight/2;
				
			// OK, the caller should have told us where they want us to align our selection,
			// relative to the component. If they didn't tell us, then we'll just assume we want
			// to try and align it with the center of the component.
			if(isNaN(selectionBaselineTarget))
				selectionBaselineTarget = unscaledHeight/2;
				
			// now that we have our anchor point in the stack, and our target location for it,
			// calculate how much we need to shift the renderers to line those two numbers up.
			var verticalOffset:Number = selectionBaselineTarget - selectionBaseline ;
			// we don't want to burst out of the bounds of our component. So if 
			// lining those two numbers up would push the stack off the top, reduce the adjustment			
			// to get as close as we can
			if(verticalOffset + details.top < GAP_FROM_TOP_EDGE)
				verticalOffset = GAP_FROM_TOP_EDGE-details.top;
			// same check to make sure our stack doesn't burst off the bottom of the component.
			if(stackHeight + verticalOffset > unscaledHeight - GAP_FROM_TOP_EDGE)
				verticalOffset = unscaledHeight - GAP_FROM_TOP_EDGE - stackHeight;
			
			// alright, we've got a safe adjustment calculated, so
			// let's shift our renderers.
			for(i = 0;i<instances.length;i++)
			{
				inst = instances[i];
				inst.move(inst.x,inst.y + verticalOffset);
			}
			
			// update our details.
			details.selectionBaseline = selectionBaseline + verticalOffset;
			details.top += verticalOffset;
			details.bottom += verticalOffset;
			
			// our layout pass tries to line up our selections. Since we can't guarantee
			// that our selection will end up in the middle of the component (if, for example,
			// our stack would have pushed off the edge), we need to tell the caller where
			// our anchor point ended up.			
			return selectionBaseline + verticalOffset;
		}

		override protected function keyDownHandler(event:KeyboardEvent):void
		{
			var n:int = _renderers.length;

			var node:XML;
			if (_highlightedNode != null)
				node = _highlightedNode;
			else if (_renderers.length > 0)
			{
				var stack:Array = _renderers[_renderers.length-1];
				node = instanceToData(stack[stack.length-1]);
			} 
			else
			{
				return;
			}
			var m:int = node.parent().children().length();
			var index:int = node.childIndex();

			switch (event.keyCode)
			{
			case Keyboard.DOWN:
					index = (index + 1) % m;
					_highlightedNode = node.parent().children()[index];
					invalidateDisplayList();
					break;
			case Keyboard.UP:
					index -= 1;
					if (index < 0)
						index += m;
					_highlightedNode = node.parent().children()[index];
					invalidateDisplayList();
					break;
			case Keyboard.RIGHT:					
			case Keyboard.ENTER:
					expandItem(node);
					_highlightedNode = (node.children().length() > 0)? node.children()[0]:node;
					break;
			case Keyboard.LEFT:					
					var p2:XML;
					if(_selectedPathIndices.length == _renderers.length)
					{
						// if our selected path is the same length as our renderer
						// count, it means that our last selected item was a leaf node.
						// which means we only want to back up a single level.
						p2 = node.parent();										
						if(p2 != null)
							expandItem(p2);
						_highlightedNode = node;
					}
					else
					{
						// our node is pointing to an item in a set of children with no
						// selected item. We want to back up and select its parent's parent,
						// which means its parent will be in the set of children with no selection.
						p2 = node.parent().parent();
						if(p2 != null)
							expandItem(p2);
						_highlightedNode = node.parent();
					}
					break;
			}
		}
		
		/*  ----------------------------------------------------------------------------------------
		/  History Management
		*/
		
		public function loadState(state:Object):void
		{
			if (state != null)
			{
				// extract the path from the state object and assign values
				// to the _selectedPathIndices array
				var path:Array = state.path.split(",");
				_selectedPathIndices = new Array(path.length);
				for (var i:int = 0; i < _selectedPathIndices.length; i++)
					_selectedPathIndices[i] = int(path[i]);
			}
			else
			{
				// no state object (initial state)
				_selectedPathIndices = [];
			}
				
			// 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.
			invalidateProperties();						
		}
		public function saveState():Object
		{
			// return a state object containing the path as a comma-separated
			// string of index values
			return {path: _selectedPathIndices.join(",")};
		}
		
		private function addedHandler(event:Event):void
		{
			if (event.target != this)
				return;

			if (historyManagementEnabled)				
				// if this object has been added to the display list,
				// register it with the history manager
				HistoryManager.register(this);
		}
		private function removedHandler(event:Event):void
		{
			if (event.target != this)
				return;

			if (historyManagementEnabled)				
				// if this object has been removed from the display list,
				// unregister it from the history manager
				HistoryManager.unregister(this);
		}
	}
}

// This is a utility class that the layout routine for our component uses. Flex allows you to declare classes inside the file, outside of the package declaration. 
// These classes are visible only to code inside this file.  This is a useful way to create small utility structs and classes meant only for implementation purposes.
class StackDetails
{
	// the position top of the stack, in pixels
	public var top:Number;
	// the position of the bottom of the stack, in pixels;
	public var bottom:Number;
	// the position of the left of the stack, in pixels;
	public var left:Number;
	// the position of the right of the stack, in pixels;
	public var right:Number;
	// the index of the selected item in the stack, if it exists. NaN otherwise.
	public var selectedIndex:Number;
	// the vertical position of the baseline of the selected item in the stack, if it exists, in pixels.
	public var selectionBaseline:Number;
}

⌨️ 快捷键说明

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