flex设计器功能拆分之二(撤销与恢复)

撤销与恢复主要用到了命令模式,也许还会和其他模式相结合:


flex设计器功能拆分之二(撤销与恢复)
 

package org.forever.drawlines
{
	//命令接口
	public interface Command
	{
		 function execute():void;//执行操作
		 function unexecute():void;//取消操作
		 function canExecute():Boolean;//是否允许执行操作
		 function canUnexecute():Boolean;//是否允许取消操作
	}
}

 

package org.forever.drawlines
{
	//命令集合类,负责存储执行过的命令和撤销执行的命令
	public class CommandList
	{
		private var _executedCommands:Array = new Array();
		private var _unexecutedCommands:Array = new Array();
		
		private function _execute(command:Command):void{
			command.execute();//执行具体的命令
			_executedCommands.push(command);//记录执行的命令
		}
		
		public function execute(command:Command):void{
			_unexecutedCommands = new Array();
			_execute(command);
		}
		
		//撤销执行,每执行一次该方法,将从最近的一次操作开始撤销
		public function unexecute():void{
			var command:Command = _executedCommands.pop();//出栈最后一次执行命令
			command.unexecute();//撤销该命令的执行
			_unexecutedCommands.push(command);//记录撤销的命令
		}
		
		//恢复执行,每执行一次该方法,将从最近的一次操作开始撤销
		public function reexecute():void{
			var command:Command = _unexecutedCommands.pop();//出栈最后一次撤销命令
			_execute(command);//重新执行
		}
		
		public function reset():void{
			_executedCommands = new Array();
			_unexecutedCommands = new Array();
		}
		
		//是否允许撤销命令,没有执行过命令就不存在撤销
		public function canUnexecuteCommand():Boolean{
			return !(_executedCommands.length==0);
		}
		
		//是否允许恢复命令,没有撤销过命令就不存在恢复
		public function canReexecuteCommand():Boolean{
			return !(_unexecutedCommands.length==0);
		}
		
	}
}

 

package org.forever.drawlines
{
	//添加线命令类
	public class AddLineCommand implements Command
	{
		private var _drawing:Drawing;//画布
		private var _line:Line;//直线
		
		
		public function AddLineCommand(drawing:Drawing,line:Line)
		{
			this._drawing = drawing;
			this._line = line;
		}
		
		public function execute():void
		{
			_drawing.add(_line);
		}
		
		public function unexecute():void
		{
			_drawing.remove(_line);
		}
		
		public function canExecute():Boolean
		{
			return true;
		}
		
		public function canUnexecute():Boolean
		{
			return true;
		}
	}
}

 

package org.forever.drawlines
{
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
	import mx.collections.ArrayList;
	import mx.controls.Alert;
	
	import spark.components.BorderContainer;
	
	//(接收者,负责具体实施和执行一个请求)画布,可以在该画布上画任意条直线
	public class Drawing extends BorderContainer
	{
		private var _application:DrawLines;//应用程序
		private var _lines:ArrayList;//直线集合
		private var _startPosition:Point;//画线开始位置
		private var _mousePosition:Point;//鼠标位置
		private var _mousePressed:Boolean;//鼠标是否按下
		private var _currentLine:Line;//正在画的直线
		
		public function Drawing(owner:DrawLines)
		{
			_application = owner;
			_lines = new ArrayList();
			_mousePressed = false;//默认鼠标未按下
			addEventListener(MouseEvent.MOUSE_DOWN,mouseDownHandler);
			addEventListener(MouseEvent.MOUSE_UP,mouseUpHandler);
			addEventListener(MouseEvent.MOUSE_MOVE,mouseMoveHandler);
			
		}
		
	
		
		//鼠标按键在组件上按下时调用
		public function mouseDownHandler(event:MouseEvent):void{
			_mousePressed = true;//鼠标为按下状态
			_startPosition = new Point(mouseX,mouseY);//记录下直线的开始位置
			_currentLine = new Line(_startPosition,_startPosition);
			addElement(_currentLine);
		}
		
		
		public function mouseUpHandler(event:MouseEvent):void{
			
			if(mouseX!=_startPosition.x&& mouseY!=_startPosition.y){//两点不重合
				var _addLineCommand:AddLineCommand = new AddLineCommand(this,_currentLine);//创建添加直线的一个命令
				_application.execute(_addLineCommand);//请求者请求命令的执行
			}else{//两点重合,不画直线
				removeElement(_currentLine);
			}
			_mousePressed = false;//未按下状态
		}
		
		public function mouseMoveHandler(event:MouseEvent):void{
			if(_mousePressed){//画线进行中......
				_mousePosition = new Point(mouseX,mouseY);
				_currentLine.end = _mousePosition;
				_currentLine.draw();
			}
		}
		
		public function add(line:Line):void{
			_lines.addItem(line);
			if(!contains(line)){
				addElement(line);
			}
		}
		
		public function remove(line:Line):void{
			_lines.removeItem(line);
			removeElement(line);
		}
		
	}
}

 

package org.forever.drawlines
{
	import flash.display.Graphics;
	import flash.geom.Point;
	
	import mx.core.UIComponent;

	public class Line extends UIComponent
	{
		
		public var x1:int;
		public var y1:int;
		public var x2:int;
		public var y2:int;
		public var _length:int;
		
		private var _start:Point;
		private var _end:Point;
		
		public function Line(start:Point,end:Point)
		{
			this.x1 = start.x;
			this.y1 = start.y;
			this.x2 = end.x;
			this.y2 = end.y;
			//_length = Number(Math.sqrt(Math.pow((x2-x1),2)+Math.pow((y2-y1),2)).toFixed());
		}
		
		public function get end():Point
		{
			return _end;
		}

		public function set end(value:Point):void
		{
			_end = value;
			x2 = end.x;
			y2 = end.y;
		}

		public function get start():Point
		{
			return _start;
		}

		public function set start(value:Point):void
		{
			_start = value;
			x1 = start.x;
			y1 = start.y;
		}

		public function draw():void{
			this.graphics.clear();
			this.graphics.moveTo(x1,y1);
			this.graphics.beginFill(0x00FF00);
			this.graphics.lineTo(x2, y2);
			this.graphics.lineStyle(2, 0x0000a00);
			this.graphics.endFill();
		}
	}
}

 

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark" 
			   xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
			   creationComplete="init()" xmlns:drawlines="org.forever.drawlines.*">
	<fx:Script>
		<![CDATA[
			import mx.controls.Alert;
			
			import org.forever.drawlines.Command;
			import org.forever.drawlines.CommandList;
			import org.forever.drawlines.Drawing;
			
			private var _drawing:Drawing;
			private var _commands:CommandList;
		
			
			//请求者(负责调用命令对象执行请求)
			public function init():void{
				_commands = new CommandList();
				_drawing = new Drawing(this);
				_drawing.x = 0;
				_drawing.y = 0;
				_drawing.percentWidth = 100;
				_drawing.percentHeight = 100;
				vg.addElement(_drawing);
				
				undoButton.addEventListener(MouseEvent.MOUSE_DOWN,undoMouseDownHandler);
				redoButton.addEventListener(MouseEvent.MOUSE_DOWN,redoMouseDownHandler);
				resetButton.addEventListener(MouseEvent.MOUSE_DOWN,resetMouseDownHandler);
				
				this.addEventListener(KeyboardEvent.KEY_DOWN,appKeyDownHandler);
				this.addEventListener(KeyboardEvent.KEY_UP,appKeyUpHandler);
				this.setFocus();
			}

			public function appKeyDownHandler(event:KeyboardEvent):void{
				
			}
			
			public function appKeyUpHandler(event:KeyboardEvent):void{
				
			}
			
			public function undoMouseDownHandler(event:MouseEvent):void{
				_commands.unexecute();
				updateButtons();
			}
			
			public function redoMouseDownHandler(event:MouseEvent):void{
				_commands.reexecute();
				updateButtons();
			}
			
			public function resetMouseDownHandler(event:MouseEvent):void{
				_commands.reset();
				updateButtons();
			}
			
			public function execute(command:Command):void{
				_commands.execute(command);// 执行命令
				updateButtons();
			} 
			
			// 更新按钮状态(根据是否能够undo撤销或者是否能够redo恢复)
			private function updateButtons():void {
				undoButton.enabled = _commands.canUnexecuteCommand();
				redoButton.enabled = _commands.canReexecuteCommand();
			}
			
		]]>
	</fx:Script>
	<fx:Declarations>
		<!-- 将非可视元素(例如服务、值对象)放在此处 -->
	</fx:Declarations>
	
	
	<s:VGroup x="0" y="0" width="100%" height="100%" id="vg">
		<s:HGroup width="100%" height="34" verticalAlign="middle">
			<s:Button x="0" y="1" label="撤销" id="undoButton"/>
			<s:Button x="82" y="0" label="重做" id="redoButton"/>
			<s:Button x="160" y="0" label="重置" id="resetButton"/>
		</s:HGroup>
		
	</s:VGroup>
</s:Application>

 

你可能感兴趣的:(设计模式,应用服务器,Flex,Flash,Adobe)