当前位置: 代码迷 >> Web前端 >> 仿IBM-BPM Editor兑现的WorkFlowEditor
  详细解决方案

仿IBM-BPM Editor兑现的WorkFlowEditor

热度:247   发布时间:2012-10-30 16:13:35.0
仿IBM-BPM Editor实现的WorkFlowEditor
    在网上搜了一些例子,找了一大队资料,终于把workFlowEditor做得差不多了,这是一个类似IBM-BPM Editor的工作流编辑器,现还有一些功能没实现,现将部分代码贴在此,有需要的朋友可以交流,拍砖,哈哈。

上图:


节点间的连线重绘:
package com
{
	import flash.geom.Point;
	
	public class RefreshLine
	{
		/** 和节点相关的线条的数组 **/
		public var lineList:Array = [];
		
		public var width:Number;
		public var height:Number;
		public var lineFlag:LineLag;
		public var line:Line;
		public var node:Nodes;
		private var isFromNode:Boolean=false;
		private var num1:int=0;		//开始节点,箭头右方向,连线数累加
		private var num2:int=0;		//开始节点,箭头左方向,连线数累加
		private var num3:int=0;		//开始节点,箭头上方向,连线数累加
		private var num4:int=0;		//开始节点,箭头下方向,连线数累加
		private var numA:int=0;		//结束节点,箭头右方向,连线数累加
		private var numB:int=0;		//结束节点,箭头左方向,连线数累加
		private var numC:int=0;		//结束节点,箭头上方向,连线数累加
		private var numD:int=0;		//结束节点,箭头下方向,连线数累加
		private var startX:int;
		private var startY:int;
		private var endX:int;
		private var endY:int;
		
		
		public function RefreshLine(node:Nodes)
		{
			this.node=node;
			lineList=node.lineList;
		}
		
		/**
		 * 重绘节点上的连线
		 * */
		public function getAspectArr():void{
			for(var j:int = 0; j < lineList.length; j++){
				lineFlag = lineList[j];
				line = lineFlag.line;
				
				switch(line.aspect){
					case 1:
						if(line.fromNode==node)
							num1++;
						else
							numA++;
						break;
					case 2:
						if(line.fromNode==node)
							num2++;
						else
							numB++;
						break;
					case 3:
						if(line.fromNode==node)
							num3++;
						else
							numC++;
						break;
					case 4:
						if(line.fromNode==node)
							num4++;
						else
							numD++;
						break;
				}
			}
		}
		
		public function refreshLine():void{
			var isHead:Boolean;
			var startNO:int=0;	//指向开始节点的连线的条数
			var endNO:int=0;	//指向结束节点的连线的条数
			
			width=node.width;
			height=node.height;
			getAspectArr();
			
			for(var i:int = 0; i < lineList.length; i++){
				startX = node.x;
				startY = node.y;
				endX = node.x;
				endY = node.y;
				lineFlag = lineList[i];
				line = lineFlag.line;
				isHead = lineFlag.isHead;
				
				if(line.fromNode==node){
					isFromNode=true;
					startNO++;
				}else{
					endNO++;
				}
				
				switch(node.type){
					case Nodes.NODE:
					case Nodes.EMAIL:
					case Nodes.CLOCK:
					case Nodes.ENDNODE:
						circleNodePosition(startNO,endNO);
						break;
					case Nodes.RECT:
						rectNodePosition(startNO,endNO);
						break;
					case Nodes.BRECT:
						rectNodePosition(startNO,endNO);
						break;
					case Nodes.DIAMOND:
						diamondNodePosition(startNO,endNO);
						break;
				}
				/**
				 * 如果是连线箭头所指的,则重设线条开始位置
				 * 如果不是,则重设连线结束
				 **/ 
				if(isHead)
					line.startPoint = new Point(startX,startY);
				else
					line.endPoint = new Point(endX,endY); 
				
				line.drawLine(line.aspect);
			}
			num1=0;
			num2=0;
			num3=0;
			num4=0;
			numA=0;
			numB=0;
			numC=0;
			numD=0;
		}
		
		private function circleNodePosition(startNO:int,endNO:int):void{
			switch(line.aspect){
				case 1:
					//箭头向右
					switch(line.lineStyle){
						case line.lineStyleArr[1]:
							if(line.fromNode.y<line.toNode.y){
								startY+=Nodes.CIRCLE_RADIUS*2+1;
							}else{
								startY-=1;
							}
							startX+=width/2-Nodes.CIRCLE_RADIUS+Nodes.CIRCLE_RADIUS*2/(num1+1)*(startNO);
							break;
						case line.lineStyleArr[2]:
							startX+=13;
							startY+=Nodes.CIRCLE_RADIUS*2/(num1+1)*(startNO);
							break;
						default:
							startX+=width-15;
							startY+=Nodes.CIRCLE_RADIUS*2/(num1+1)*(startNO);
							break;
					}
					endX+=15;
					endY+=Nodes.CIRCLE_RADIUS*2/(numA+1)*(endNO);
					break;
				case 2:
					//箭头向左
					switch(line.lineStyle){
						case line.lineStyleArr[1]:
							if(line.fromNode.y<line.toNode.y){
								startY+=Nodes.CIRCLE_RADIUS*2+1;
							}else{
								startY-=1;
							}
							startX+=width/2-Nodes.CIRCLE_RADIUS+Nodes.CIRCLE_RADIUS*2/(num2+1)*(startNO);
							break;
						case line.lineStyleArr[2]:
							startX+=width-15;
							startY+=Nodes.CIRCLE_RADIUS*2/(num2+1)*(startNO);
							break;
						default:
							startX+=13;
							startY+=Nodes.CIRCLE_RADIUS*2/(num2+1)*(startNO);
							break;
					}
					endX+=width-13;
					endY+=Nodes.CIRCLE_RADIUS*2/(numB+1)*(endNO);
					break;
				case 3:
					//箭头向上
					switch(line.lineStyle){
						case line.lineStyleArr[1]:
							if(line.fromNode.x<line.toNode.x){
								startX+=width-15;
							}else{
								startX+=13;
							}
							startY+=Nodes.CIRCLE_RADIUS*2/(num3+1)*(startNO);
							break;
						case line.lineStyleArr[2]:
							startX+=width/2-Nodes.CIRCLE_RADIUS+Nodes.CIRCLE_RADIUS*2/(num3+1)*(startNO);
							startY+=Nodes.CIRCLE_RADIUS*2+1;
							break;
						default:
							startX+=width/2-Nodes.CIRCLE_RADIUS+Nodes.CIRCLE_RADIUS*2/(num3+1)*(startNO);
							startY-=1;
							break;
					}
					endX+=width/2-Nodes.CIRCLE_RADIUS+Nodes.CIRCLE_RADIUS*2/(numC+1)*(endNO);
					endY+=Nodes.CIRCLE_RADIUS*2+3;
					break;
				case 4:
					//箭头向下
					switch(line.lineStyle){
						case line.lineStyleArr[1]:
							if(line.fromNode.x<line.toNode.x){
								startX+=width-15;
							}else{
								startX+=13;
							}
							startY+=Nodes.CIRCLE_RADIUS*2/(num4+1)*(startNO);
							break;
						case line.lineStyleArr[2]:
							startX+=width/2-Nodes.CIRCLE_RADIUS+Nodes.CIRCLE_RADIUS*2/(num4+1)*(startNO);
							startY-=1;
							break;
						default:
							startX+=width/2-Nodes.CIRCLE_RADIUS+Nodes.CIRCLE_RADIUS*2/(num4+1)*(startNO);
							startY+=Nodes.CIRCLE_RADIUS*2+1;
							break;
					}
					endX+=width/2-Nodes.CIRCLE_RADIUS+Nodes.CIRCLE_RADIUS*2/(numD+1)*(endNO);
					endY-=2;
					break;
			}
		}
		
		private function rectNodePosition(startNO:int,endNO:int):void{
			switch(line.aspect){
				case 1:
					switch(line.lineStyle){
						case line.lineStyleArr[1]:
							if(line.fromNode.y<line.toNode.y){
								startY+=height+2;
							}else{
								startY-=0;
							}
							startX+=width/(num1+1)*(startNO);
							break;
						case line.lineStyleArr[2]:
							startX-=0;
							startY+=height/(num1+1)*(startNO);
							break;
						default:
							startX+=width;
							startY+=height/(num1+1)*(startNO);
							break;
					}
					endX-=2;
					endY+=height/(numA+1)*(endNO);
					break;
				case 2:
					switch(line.lineStyle){
						case line.lineStyleArr[1]:
							if(line.fromNode.y<line.toNode.y){
								startY+=height+2;
							}else{
								startY-=0;
							}
							startX+=width/(num2+1)*(startNO);
							break;
						case line.lineStyleArr[2]:
							startX+=width;
							startY+=height/(num2+1)*(startNO);
							break;
						default:
							startX-=0;
							startY+=height/(num2+1)*(startNO);
							break;
					}
					endX+=width+2;
					endY+=height/(numB+1)*(endNO);
					break;
				case 3:
					switch(line.lineStyle){
						case line.lineStyleArr[1]:
							if(line.fromNode.x<line.toNode.x){
								startX+=width;
							}else{
								startX-=0;
							}
							startY+=height/(num3+1)*(startNO);
							break;
						case line.lineStyleArr[2]:
							startX+=width/(num3+1)*(startNO);
							startY+=height+2;
							break;
						default:
							startX+=width/(num3+1)*(startNO);
							startY-=0;
							break;
					}
					endX+=width/(numC+1)*(endNO);
					endY+=height+3;
					break;
				case 4:
					switch(line.lineStyle){
						case line.lineStyleArr[1]:
							if(line.fromNode.x<line.toNode.x){
								startX+=width;
							}else{
								startX-=0;
							}
							startY+=height/(num4+1)*(startNO);
							break;
						case line.lineStyleArr[2]:
							startX+=width/(num4+1)*(startNO);
							startY-=0;
							break;
						default:
							startX+=width/(num4+1)*(startNO);
							startY+=height+2;
							break;
					}
					endX+=width/(numD+1)*(endNO);
					endY-=1;
					break;
			}
		}
		
		private function diamondNodePosition(startNO:int,endNO:int):void{
			switch(line.aspect){
				case 1:
					if((num1<=1 && line.fromNode==node) || (numA<=1 && line.toNode==node)){
						switch(line.lineStyle){
							case line.lineStyleArr[1]:
								if(line.fromNode.y<line.toNode.y){
									startY+=Nodes.DIAMOND_BORDER;
								}else{
									startY-=0;
								}
								startX+=width/2;
								break;
							case line.lineStyleArr[2]:
								startX+=4;
								startY+=Nodes.DIAMOND_BORDER/(num1+1)*(startNO);
								break;
							default:
								startX+=Nodes.DIAMOND_BORDER+6;
								startY+=Nodes.DIAMOND_BORDER/2;
								break;
						}
						endX+=3;
						endY+=Nodes.DIAMOND_BORDER/2;
					}else{
						switch(line.lineStyle){
							case line.lineStyleArr[1]:
								if(line.fromNode.y<line.toNode.y){
									startY+=Nodes.DIAMOND_BORDER-13;
								}else{
									startY+=13;
								}
								startX+=width/(num1+1)*(startNO);
								break;
							case line.lineStyleArr[2]:
								startX+=(width-Nodes.DIAMOND_BORDER)/2+10;
								startY+=Nodes.DIAMOND_BORDER/(num1+1)*(startNO);
								break;
							default:
								startX+=Nodes.DIAMOND_BORDER-6;
								startY+=Nodes.DIAMOND_BORDER/(num1+1)*(startNO);
								break;
						}
						endY+=Nodes.DIAMOND_BORDER/(numA+1)*(endNO);
						
						if((num1==3 && startNO==2) || (numA==3 && endNO==2)){
							endX+=3;
						}else{
							endX+=15;
						}
					}
					break;
				case 2:
					if((num2<=1 && line.fromNode==node) || (numB<=1 && line.toNode==node)){
						switch(line.lineStyle){
							case line.lineStyleArr[1]:
								if(line.fromNode.y<line.toNode.y){
									startY+=Nodes.DIAMOND_BORDER;
								}else{
									startY-=0;
								}
								startX+=width/2;
								break;
							case line.lineStyleArr[2]:
								startX+=Nodes.DIAMOND_BORDER+6;
								startY+=Nodes.DIAMOND_BORDER/(num2+1)*(startNO);
								break;
							default:
								startX+=4;
								startY+=Nodes.DIAMOND_BORDER/2;
								break;
						}
						endX+=Nodes.DIAMOND_BORDER+6;
						endY+=Nodes.DIAMOND_BORDER/2;
					}else{
						switch(line.lineStyle){
							case line.lineStyleArr[1]:
								if(line.fromNode.y<line.toNode.y){
									startY+=Nodes.DIAMOND_BORDER-13;
								}else{
									startY+=13;
								}
								startX+=width/(num2+1)*(startNO);
								break;
							case line.lineStyleArr[2]:
								startX+=Nodes.DIAMOND_BORDER-6;
								startY+=Nodes.DIAMOND_BORDER/(num2+1)*(startNO);
								break;
							default:
								startX+=(width-Nodes.DIAMOND_BORDER)/2+13;
								startY+=Nodes.DIAMOND_BORDER/(num2+1)*(startNO);
								break;
						}
						endY+=Nodes.DIAMOND_BORDER/(numB+1)*(endNO);
						
						if((num2==3 && startNO==2) || (numB==3 && endNO==2)){
							endX+=Nodes.DIAMOND_BORDER+7;
						}else{
							endX+=Nodes.DIAMOND_BORDER-4;
						}
					}
					break;
				case 3:
					if((num3<=1 && line.fromNode==node) || (numC<=1 && line.toNode==node)){
						switch(line.lineStyle){
							case line.lineStyleArr[1]:
								if(line.fromNode.x<line.toNode.x){
									startX+=Nodes.DIAMOND_BORDER+6;
								}else{
									startX+=4;
								}
								startY+=Nodes.DIAMOND_BORDER/2;
								break;
							case line.lineStyleArr[2]:
								startX+=width/(num3+1)*(startNO);
								startY+=Nodes.DIAMOND_BORDER;
								break;
							default:
								startX+=width/2;
								startY-=0;
								break;
						}
						endX+=width/2;
						endY+=Nodes.DIAMOND_BORDER+2;
					}else{
						switch(line.lineStyle){
							case line.lineStyleArr[1]:
								if(line.fromNode.x<line.toNode.x){
									startX+=Nodes.DIAMOND_BORDER-13;
								}else{
									startX+=15;
								}
								startY+=Nodes.DIAMOND_BORDER/(num3+1)*(startNO);
								break;
							case line.lineStyleArr[2]:
								startX+=width/(num3+1)*(startNO);
								startY+=Nodes.DIAMOND_BORDER-13;
								break;
							default:
								startX+=width/(num3+1)*(startNO);
								startY+=13;
								break;
						}
						endX+=width/(numC+1)*(endNO);
						if((num3==3 && startNO==2) || (numC==3 && endNO==2)){
							endY+=Nodes.DIAMOND_BORDER+2;
						}else{
							endY+=Nodes.DIAMOND_BORDER-11;
						}
					}
					break;
				case 4:
					if((num4<=1 && line.fromNode==node) || (numD<=1 && line.toNode==node)){
						switch(line.lineStyle){
							case line.lineStyleArr[1]:
								if(line.fromNode.x<line.toNode.x){
									startX+=Nodes.DIAMOND_BORDER+6;
								}else{
									startX+=4;
								}
								startY+=Nodes.DIAMOND_BORDER/2;
								break;
							case line.lineStyleArr[2]:
								startX+=width/(num4+1)*(startNO);
								startY-=0;
								break;
							default:
								startX+=width/2;
								startY+=Nodes.DIAMOND_BORDER;
								break;
						}
						endX+=width/2;
						endY-=1;
					}else{
						switch(line.lineStyle){
							case line.lineStyleArr[1]:
								if(line.fromNode.x<line.toNode.x){
									startX+=Nodes.DIAMOND_BORDER-13;
								}else{
									startX+=15;
								}
								startY+=Nodes.DIAMOND_BORDER/(num4+1)*(startNO);
								break;
							case line.lineStyleArr[2]:
								startX+=width/(num4+1)*(startNO);
								startY+=13;
								break;
							default:
								startX+=width/(num4+1)*(startNO);
								startY+=Nodes.DIAMOND_BORDER-13;
								break;
						}
						endX+=width/(numD+1)*(endNO);
						if((num4==3 && startNO==2) || (numD==3 && endNO==2)){
							endY-=1;
						}else{
							endY+=11;
						}
					}
					break;
			}
		}
		
	}
}


键盘事件类:
package com
{
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	
	import mx.core.UITextField;
	
	import net.L4cd.iTrace;
	
	public class WFKeyboard
	{
		private var node:Nodes;
		private var line:Line;
		private var workFlow:CusWorkFlow;
		private var o:Object;
		/** CusWorkFlow对象的放大/缩小参数 **/
		private var scaleNO:Number=.2;
		/** 封装连线的对象 **/
		private var lineLag1:LineLag;
		
		public var trace:Function = iTrace.init;
		
		public function WFKeyboard()
		{
			
		}
		
		/** 选择键盘按键ASCII值 **/
		public function chooseKey(e:KeyboardEvent,mouseE:MouseEvent):void {
			o=getObjects(mouseE);
			node=o.node as Nodes;
			line=o.line as Line;
			workFlow=o.workFlow as CusWorkFlow;
			switch(e.keyCode){
				case 8:
				case 46:
					deleteNode(node,line,workFlow);
					break;
				case 65:
					if(!e.ctrlKey)return;
					
					break;
				case 107:
					if(!e.ctrlKey)return;
					workFlow.scaleX+=scaleNO;//放大CusWorkFlow对象
					workFlow.scaleY+=scaleNO;
					break;
				case 109:
					if(!e.ctrlKey)return;
					workFlow.scaleX-=scaleNO;//缩小CusWorkFlow对象
					workFlow.scaleY-=scaleNO;
					break;
			}
		}
		
		/** 删除节点或连线 **/
		private function deleteNode(node:Nodes,line:Line,workFlow:CusWorkFlow):void {
			if(!workFlow)return;
			
			if(node){
				var num:int=node.lineList.length;
				for(var i:int=0;i<num;i++){
					var lineLag:LineLag=node.lineList[i];
					workFlow.removeChild(lineLag.line);
					
					if(node==lineLag.line.fromNode){
						for(var j:int=0;j<lineLag.line.toNode.lineList.length;j++){
							lineLag1=lineLag.line.toNode.lineList[j] as LineLag;
							if(node==lineLag1.line.fromNode){
								lineLag.line.toNode.lineList.splice(j,1);
							}
						}
					}else{
						for(var k:int=0;k<lineLag.line.fromNode.lineList.length;k++){
							lineLag1=lineLag.line.fromNode.lineList[k] as LineLag;
							if(node==lineLag1.line.toNode){
								lineLag.line.fromNode.lineList.splice(k,1);
							}
						}
					}
				}
				
				workFlow.removeChild(node);
			}else if(line){
				for(var m:int=0;m<line.toNode.lineList.length;m++){
					lineLag1=line.toNode.lineList[m] as LineLag;
					if(line==lineLag1.line){
						line.toNode.lineList.splice(m,1);
						break;
					}
				}
				
				for(var n:int=0;n<line.fromNode.lineList.length;n++){
					lineLag1=line.fromNode.lineList[n] as LineLag;
					if(line==lineLag1.line){
						line.fromNode.lineList.splice(n,1);
					}
				}
				workFlow.removeChild(line);
			}
		}
		
		/** 重画节点边框,表示选中或非选中 **/
		public function reDrawNode(map:Nodes):void{
			switch(map.type){
				case Nodes.NODE:
					map.drawNode();
					break;
				case Nodes.DOC:
					map.drawDoc();
					break;
				case Nodes.EMAIL:
					map.drawEmail();
					break;
				case Nodes.RECT:
					map.drawRect();
					break;
				case Nodes.BRECT:
					map.drawBRect();
					break;
				case Nodes.DIAMOND:
					map.drawDiamond();
					break;
				case Nodes.CLOCK:
					map.drawClock();
					break;
				case Nodes.ENDNODE:
					map.drawEndNode();
					break;
				case Nodes.LEFTDASHED:
					map.drawDashed();
					break;
				case Nodes.RIGHTDASHED:
					map.drawDashed2();
					break;
			}
		}
		
		/** 返回鼠标选中的对象 **/
		private function getObjects(e:MouseEvent):Object{
			o=new Object();
			if(e.target is UITextField){
				o.node=e.target.parent.parent as Nodes;
				o.workFlow=e.target.parent.parent.parent as CusWorkFlow;
			}else if(e.target is Nodes){
				o.node=e.target as Nodes;
				o.workFlow=e.target.parent as CusWorkFlow;
			}else if(e.target is CusWorkFlow){
				o.workFlow=e.target as CusWorkFlow;
			}else if(e.target is Line){
				o.line=e.target as Line;
				o.workFlow=e.target.parent as CusWorkFlow;
			}
			return o;
		}
	}
}


1 楼 tree_161219 2011-03-29  
写的很不错呢!
2 楼 debbykindom 2011-09-16  
,强大,希望有机会再和兄台深入交流。
3 楼 a0409028 2011-10-19  
能不能共享一下,页面源码
4 楼 shlei 2011-10-19  
a0409028 写道
能不能共享一下,页面源码

抱歉,这已经是商业产品了,
5 楼 a0409028 2011-11-11  
连线是怎么实现的有弧度,据天代码是那块?,感谢 了。
6 楼 shlei 2011-11-11  
a0409028 写道
连线是怎么实现的有弧度,据天代码是那块?,感谢 了。

二次贝塞尔曲线,查资料吧,
7 楼 421081646 2012-08-08  
挺好的,学习了
8 楼 jcl860 2012-08-30  
兄弟, import com.ibm.ilog.elixir.diagram.Graph;缺这些东西啊,这些东西报错了,咋整呢?
9 楼 shlei 2012-08-30  
jcl860 写道
兄弟, import com.ibm.ilog.elixir.diagram.Graph;缺这些东西啊,这些东西报错了,咋整呢?

你这个是用的ilog组件,需要导入ilog的swc库文件,
10 楼 jcl860 2012-08-31  
兄弟,你有联系方式没有,请给发一下。我的邮箱:317902593@qq.com。
11 楼 shlei 2012-08-31  
jcl860 写道
兄弟,你有联系方式没有,请给发一下。我的邮箱:317902593@qq.com。

这里有,自己下载吧,http://www.ibm.com/developerworks/cn/downloads/ws/elixir/
12 楼 jcl860 2012-09-05  
兄弟,能把mxml代码贴上看看不,主要是画不出界面啊。
13 楼 jcl860 2012-09-14  
兄台:左边面板是图片,还是用mxml画出来的图形?
  相关解决方案