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

📄 selectioncontrol.as

📁 用于flash/flex的 as3的 2D图形图像图表的动态生成
💻 AS
字号:
package flare.vis.controls
{
	import flare.vis.events.SelectionEvent;
	
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Graphics;
	import flash.display.InteractiveObject;
	import flash.display.Shape;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	import flash.utils.Dictionary;

	[Event(name="select",   type="flare.vis.events.SelectionEvent")]
	[Event(name="deselect", type="flare.vis.events.SelectionEvent")]
	
	/**
	 * Interactive control for selecting a group of objects by "rubber-banding"
	 * them with a rectangular section region.
	 */
	public class SelectionControl extends Control
	{
		private var _r:Rectangle = new Rectangle();
		private var _drag:Boolean = false;
		private var _shape:Shape = new Shape();
		private var _hit:InteractiveObject;
		private var _stage:Stage;
		private var _sel:Dictionary = new Dictionary();
		
		private var _add0:DisplayObject = null;
		private var _rem0:DisplayObject = null;
		private var _add:Array = null;
		private var _rem:Array = null;
		
		/** The active hit area over which selection
		 *  interactions can be performed. */
		public function get hitArea():InteractiveObject { return _hit; }
		public function set hitArea(hitArea:InteractiveObject):void {
			if (_hit != null) onRemove();
			_hit = hitArea;
			if (_object && _object.stage != null) onAdd();
		}
		
		/** Indicates if a selection events should be fired immediately upon a
		 *  chane of selection status (true) or after the mouse is released
		 * (false). The default is true. Set this to false if immediate
		 * selections are causing any performance issues. */
		public var fireImmediately:Boolean = true;
		
		/** Line color of the selection region border. */
		public var lineColor:uint = 0x8888FF;
		/** Line alpha of the selection region border. */
		public var lineAlpha:Number = 0.4;
		/** Line width of the selection region border. */
		public var lineWidth:Number = 2;
		/** Fill color of the selection region. */
		public var fillColor:uint = 0x8888FF;
		/** Fill alpha of the selection region. */
		public var fillAlpha:Number = 0.2;
		
		// --------------------------------------------------------------------
		
		/**
		 * Creates a new SelectionControl.
		 * @param filter an optional Boolean-valued filter determining which
		 *  items are eligible for selection.
		 * @param hitArea a display object to use as the hit area for mouse
		 *  events. For example, this could be a background region over which
		 *  the selection can done. If this argument is null,
		 *  the stage will be used.
		 * @param select an optional SelectionEvent listener for selections
		 * @param deselect an optional SelectionEvent listener for deselections
		 */
		public function SelectionControl(filter:*=null,
			select:Function=null, deselect:Function=null,
			hitArea:InteractiveObject=null)
		{
			_hit = hitArea;
			this.filter = filter;
			if (select != null)
				addEventListener(SelectionEvent.SELECT, select);
			if (deselect != null)
				addEventListener(SelectionEvent.DESELECT, deselect);
		}
		
		/**
		 * Indicates is a display object has been selected. 
		 * @param d the display object
		 * @return true if selected, false if not
		 */
		public function isSelected(d:DisplayObject):Boolean
		{
			return _sel[d] != undefined;
		}
		
		// -----------------------------------------------------
		
		/** @inheritDoc */
		public override function attach(obj:InteractiveObject):void
		{
			if (obj==null) { detach(); return; }
			if (!(obj is DisplayObjectContainer)) {
				throw new Error("Attached object must be a DisplayObjectContainer");
			}
			super.attach(obj);
			if (obj != null) {
				obj.addEventListener(Event.ADDED_TO_STAGE, onAdd);
				obj.addEventListener(Event.REMOVED_FROM_STAGE, onRemove);
				if (obj.stage != null) onAdd();
			}
		}
		
		/** @inheritDoc */
		public override function detach():InteractiveObject
		{
			onRemove();
			if (_object != null) {
				_object.removeEventListener(Event.ADDED_TO_STAGE, onAdd);
				_object.removeEventListener(Event.REMOVED_FROM_STAGE, onRemove);
			}
			_hit = null;
			return super.detach();
		}
		
		private function onAdd(evt:Event=null):void
		{
			_stage = _object.stage;
			if (_hit == null) _hit = _stage;
			_hit.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
		}
		
		private function onRemove(evt:Event=null):void
		{
			if (_hit)
				_hit.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
		}
		
		// -----------------------------------------------------
				
		private function mouseDown(evt:MouseEvent):void
		{
			if (_stage == null) return;
			_stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
			_stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
			
			_r.x = _object.mouseX;
			_r.y = _object.mouseY;
			_r.width = 0;
			_r.height = 1;
			_drag = true;
			
			DisplayObjectContainer(_object).addChild(_shape);
			renderShape(_shape.graphics);
			if (fireImmediately) {
				selectionTest(evt);
			}
		}
		
		private function mouseMove(evt:MouseEvent):void
		{
			if (!_drag) return;
			_r.width = _object.mouseX - _r.x;
			_r.height = _object.mouseY - _r.y;
			
			renderShape(_shape.graphics);
			if (fireImmediately) {
				selectionTest(evt);
			}
		}
		
		private function mouseUp(evt:MouseEvent):void
		{
			if (!fireImmediately)
				selectionTest(evt);
			_drag = false;
			DisplayObjectContainer(_object).removeChild(_shape);
			_stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUp);
			_stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
		}
		
		private function renderShape(g:Graphics):void {
			g.clear();
			g.beginFill(fillColor, fillAlpha);
			g.lineStyle(lineWidth, lineColor, lineAlpha, true, "none");
			g.drawRect(_r.x, _r.y, _r.width, _r.height);
			g.endFill();
		}
		
		private function selectionTest(evt:MouseEvent):void {			
			var con:DisplayObjectContainer = DisplayObjectContainer(_object);
			for (var i:uint=0; i<con.numChildren; ++i) {
				walkTree(con.getChildAt(i), test);
			}
			
			// process selection events
			if (_rem0 && hasEventListener(SelectionEvent.DESELECT)) {
				dispatchEvent(new SelectionEvent(SelectionEvent.DESELECT,
					_rem ? _rem : _rem0, evt));
			}
			if (_add0 && hasEventListener(SelectionEvent.SELECT)) {
				dispatchEvent(new SelectionEvent(SelectionEvent.SELECT,
					_add ? _add : _add0, evt));
			}
			_rem = _add = null;
			_rem0 = _add0 = null;
		}
		
		private static function walkTree(obj:DisplayObject, func:Function):void
		{
			func(obj);
			if (obj is DisplayObjectContainer) {
				var con:DisplayObjectContainer = obj as DisplayObjectContainer;
				for (var i:int=0; i<con.numChildren; ++i) {
					walkTree(con.getChildAt(i), func);
				}
			}
		}
		
		private function test(d:DisplayObject):void
		{
			if (_filter!=null && !_filter(d)) return;
			var a:Boolean = _sel[d] != undefined;
			var b:Boolean = d.hitTestObject(_shape);
			
			if (!a && b && hasEventListener(SelectionEvent.SELECT)) {
				select(d);
			} else if (a && !b && hasEventListener(SelectionEvent.DESELECT)) {
				deselect(d);
			}
		}
		
		private function select(d:DisplayObject):void {
			_sel[d] = d;
			if (_add == null)
				if (_add0 == null) {
					_add0 = d;
				} else {
					_add = [_add0, d];
				}
			else
				_add.push(d);
		}
		
		private function deselect(d:DisplayObject):void {
			delete _sel[d];
			if (_rem == null)
				if (_rem0 == null) {
					_rem0 = d;
				} else {
					_rem = [_rem0, d];
				}
			else
				_rem.push(d);
		}
		
	} // end of class SelectionControl
}

⌨️ 快捷键说明

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