JAVA Applet 实现工作流设计器

很久没有更新博客了,不是偷懒,而是去年一年的时间都在编写一个快速JAVA开发框架ARK,终于有所小成,才有了闲情逸致没事写点小玩意儿,JAVA Swing自己很少关注,Applet也是如此,从学习Swing和Applet到写出这东西只花了2天时间,算是一些自己的学习心得和成果,希望各位看客多多交流,虽然Applet和Swing不是我工作的重点,偶尔当消遣了。


JAVA Applet 实现工作流设计器_第1张图片
 

 

 

言归正传,这是一个工作流系统中的流程设计器,整个设计完全面向接口,所以有比较好的扩展性,小弟我水平有限,一些功能就没有加上,有兴趣的XD可以完善这些代码(其实大部分功能都已经实现了,包括流程图路径验证,只是现在只能绘制流程生成XML,没有反向去实现将XML生成流程图),可能自己想起来会再把他翻出来改改,在某个时间将图形转换成HTML能够直接在网页上显示,为什么这么干,你懂得!!

 

package com.applet.flows;

import java.awt.Container;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.event.MouseEvent;
import java.util.Collection;
import java.util.Vector;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.TransferHandler;
import javax.swing.event.MouseInputAdapter;

import com.applet.flows.attr.NodeAttribute;
import com.applet.flows.panel.FlowLine;
import com.applet.flows.panel.FlowPanel;

public abstract class NodeButtonSupport extends JButton implements INodeButton {

	private Collection<INodeButton> childs = null;
	
	private Collection<INodeButton> parents = null;
	
	private int id = -1;
	
	protected DropTarget dropTarget = null;
	
	public NodeButtonSupport(){
		this.childs = new Vector<INodeButton>();
		this.parents = new Vector<INodeButton>();
		this.dropTarget = new DropTarget(this,DnDConstants.ACTION_COPY,this,true);
		new MouseApdaterListener(this);
		this.setSize(100, 40);
		this.setLocation(0, 45);
	}
	
	public ImageIcon getIcon(){
		return null;
	}
	
	public final String[] asXML() {
		String xml = "";
		xml = "<Node id=\"" + this.getID() + "\" type=\"" + this.getType() + "\" name=\"" + this.getText() + "\" x=\"" + this.getX() + "\" y=\"" + this.getY() + "\" />";
		String to = "";
		for(INodeButton nb:this.getChilds()){
			to += nb.getID() + ",";
		}
		String line = "";
		if(!to.trim().equals("")){
			line  = "<Line from=\"" + this.getID() + "\" to=\"" + to.substring(0,to.length() - 1) + "\" />";
		}
		return new String[]{xml,line};
	}

	public final void init(int id) {
		this.id = id;
		ImageIcon icon = this.getIcon();
		if(icon != null){
			this.setIcon(icon);
		}
		this.init();
	}
	
	public INodeButton getThis(){
		return this;
	}
	
	/**
	 * 判断当某个对象接入子对象后,是否会成为一个循环流程
	 * @param button 接入后的对象
	 * @return true:是一个循环,false:不是循环
	 */
	public boolean isPathed(INodeButton button){
		for(INodeButton nb : this.getChilds()){
			if(nb == button){
				return true;
			}
			if(nb instanceof NodeButtonSupport){
				return ((NodeButtonSupport)nb).isPathed(button);
			}
		}
		return false;
	}
	
	/**
	 * 找到Frame对象
	 * @param jc
	 * @return
	 */
	public FlowPanel getFrame(Container jc){
		if(jc == null){
			return null;
		}
		if(jc instanceof FlowPanel){
			return (FlowPanel)jc;
		}
		return this.getFrame(jc.getParent());
	}
	
	protected abstract void init();
	
	public int getID(){
		return this.id;
	}
	
	public abstract boolean link(INodeButton button);

	public void addParent(INodeButton nb){
		this.parents.add(nb);
	}
	
	public void addChild(INodeButton nb){
		this.childs.add(nb);
	}

	public void dragEnter(DropTargetDragEvent arg0) {

	}

	public void dragExit(DropTargetEvent arg0) {

	}

	public void dragOver(DropTargetDragEvent arg0) {

	}

	public final void drop(DropTargetDropEvent e) {
		DataFlavor ob = e.getCurrentDataFlavors()[0];
		try {
			if(!e.getTransferable().isDataFlavorSupported(ob)){
				JOptionPane.showMessageDialog(null, "应用程序不支持对象序列化\n[" + ob.toString() + "]","错误",JOptionPane.ERROR_MESSAGE);
				return;
			}
			INodeButton db = (INodeButton)e.getTransferable().getTransferData(ob);
			if(db == null){
				JOptionPane.showMessageDialog(null, "应用程序无法读取对象序列化\n[" + ob.toString() + "]","错误",JOptionPane.ERROR_MESSAGE);
				return;
			}
			if(isPathed(db)){
				return;
			}
			if(db.report(this) && this.link(db)){
				this.addParent(db);
				db.addChild(this);
				FlowPanel frame = this.getFrame(this.getParent());
				if(frame == null){
					JOptionPane.showMessageDialog(null, "程序无法找到父容器","错误",JOptionPane.ERROR_MESSAGE);
				}else{
					FlowLine line = new FlowLine(new JButton[]{(JButton)db,this});
					line.setSize(frame.getSize());
					line.setLocation(0,0);
					frame.add(line);
					frame.setText("[" + this.getText() + "]连线成功");
					frame.repaint();
				}
			}
		} catch (Exception e1) {
			this.getFrame(this.getParent()).setText(e1.getClass().getName());
			JOptionPane.showMessageDialog(null, e1.toString(),"错误",JOptionPane.ERROR_MESSAGE);
			e1.printStackTrace();
		}
	}
	@Override
	public void setToolTipText(String str) {
		str =  "[ID=" + this.getID() + "]\n" + str; 
		super.setToolTipText(str);
	}
	
	public void dropActionChanged(DropTargetDragEvent arg0) {

	}
	
	public final Collection<INodeButton> getChilds(){
		return this.childs;
	}
	
	public final Collection<INodeButton> getParents(){
		return this.parents;
	}

	/**
	 * 获取节点类型
	 * @return 节点类型
	 */
	public abstract String getType();
	
	public final class MouseApdaterListener extends MouseInputAdapter{
		
		private NodeButtonSupport support = null;
		
		private Point point = new Point(0, 0);   
		
		public MouseApdaterListener(NodeButtonSupport support){
			this.support = support;
			this.support.addMouseListener(this);
			this.support.addMouseMotionListener(this);
		}
		
		@Override
		public void mouseClicked(MouseEvent e) {
			new NodeAttribute(this.support).setVisible(true);
		}
		
		public void mousePressed(MouseEvent e) {
			if(e.getButton() != 1){
				JComponent com=(JComponent)e.getSource();
				TransferHandler handler = new TransferHandler("this");
				com.setTransferHandler(handler);
				handler.exportAsDrag(com, e, DnDConstants.ACTION_COPY);
			}else{
				this.point = SwingUtilities.convertPoint(this.support, e.getPoint(), this.support.getParent());
			}
		}
		
		@Override
		public void mouseDragged(MouseEvent e) {
			if(e.getButton() != 1){
				Point newPoint = SwingUtilities.convertPoint(this.support, e.getPoint(), this.support.getParent());
				Point btnPoint = new Point((this.support.getX() + (newPoint.x - this.point.x )),(this.support.getY() + (newPoint.y - this.point.y)));
				this.support.setLocation(btnPoint);
				point = newPoint;
				FlowPanel frame = this.support.getFrame(this.support.getParent());
				frame.repaint();
			}
		}
	}
}

 

强调一下,NodeButtonSupport是所有节点的抽象类,如果希望扩展节点类型的XD在增加类型的时候一定别忘了继承他,里面很多算法我都已经实现好了,当然还有两个接口。

package com.applet.flows;

/**
 * 基本XML流程对象
 * 
 * @author 熊浩华 - xionghh
 *
 * 2011-3-10:下午12:29:47-
 */
public interface IFlow {

	/**
	 * 返回该对象的XML分为{节点,连接线}
	 * @return
	 */
	public String[] asXML();
	
	/**
	 * 判断节点是否是合法
	 * @return 当节点存在异常时抛出节点异常信息,否则返回true
	 */
	public boolean checkNode() throws Exception;
	
}

  

 

 

 导出XML文档的接口,所有的节点都实现该接口用于保存时生成XML文档方便,代码派生起来也容易。

 

package com.applet.flows;

import java.awt.dnd.DropTargetListener;
import java.util.Collection;

/**
 * 流程节点接口,用于处理流程的节点
 * 
 * @author 熊浩华 - xionghh
 *
 * 2011-3-10:上午10:02:53-
 */
public interface INodeButton extends DropTargetListener,IFlow {

	/**
	 * 初始化节点对象
	 * @param id 对象ID
	 */
	public void init(int id);
	
	/**
	 * 某个节点拖入,是否允许他和你进行链接
	 * @param button 发起链接的对象
	 * @return 判断是否允许链接,返回true表示允许,false表示不允许操作
	 */
	public boolean link(INodeButton button);
	
	/**
	 * 通知节点,你被拖动到某个节点上,需要你和他进行链接
	 * @param button 需要链接的对象
	 * @return 允许链接返回true,不允许链接返回false
	 */
	public boolean report(INodeButton button);
	
	/**
	 * 获取对象ID
	 * @return 对象ID
	 */
	public int getID();
	
	/**
	 * 添加一个父对象
	 * @param nb
	 */
	public void addParent(INodeButton nb);
	
	/**
	 * 添加一个子对象
	 * @param nb
	 */
	public void addChild(INodeButton nb);
	
	/**
	 * 获取所有子对象
	 * @return
	 */
	public Collection<INodeButton> getChilds();
	
	/**
	 * 获取所有父对象
	 * @return
	 */
	public Collection<INodeButton> getParents();
	
}

 

INodeButton是所有节点的抽象接口,其实很多方法都是想到的时候补上的,开始打算写这个东西的时候没有想把他做成什么样,就当玩票,没仔细去对接口进行详细的设计,很粗略的就描绘了一下。所以看起来有点似是而非。

 

 

最后说一下Demo,压缩包里有tomcat的工程目录,XFLow直接Copy到tomcat下的webapps里就能运行,里面两个包flows.jar和dom4j-1.6.1.jar是签名过的,否则无法当成Applet运行,源码在src里,修改代码后想要在Applet测试通过记得打成包然后对包进行签名。

 

PS:呵呵,老规矩,CSDN(最近穷疯了,分不够了,希望各位给小弟我捧个场)

 

 

 

 

 下载地址 : http://download.csdn.net/source/3082444

 

你可能感兴趣的:(java,tomcat,工作,xml,swing)