这一节,我们讲控制器的设计,在gef框架中,控制器作为连接模型和视图的桥梁,它主要根据用户的操作来修改模型,并且刷新视图。在前面我们定义了流程模型(WorkflowProcess),活动模型(AbstractActivity),转移模型(Transition),在这里我们分别定义相应的控制器(EditPart),首先我们定义流程模型对应的控制器(WorkflowProcessEditPart),每个控制器都必须继承AbstractGraphicalEditPart类,并且由于控制器要作为模型的侦听器,侦听模型的变化,所以它还必须实现PropertyChangeListener接口。
在控制器生效时,应该把控制器注册为对应模型的侦听器,为此我们应该覆盖父类的activate方法,代码如下:
同时在控制器失效时,我们从模型中删除这个侦听器,代码如下:
此外由于流程控制器对应的模型,里面包含了一组活动模型,所以我们还应该覆盖父类的getModelChildren(),代码如下:
这个Figure可以向四周无限扩展,相当与一块画布一样。流程控制器的类我们先定义到这儿,到以后还要修改这个类,来实现一些功能。完整代码如下:
在这个类中activate,deactivate方法功能和流程控制器中一样,只是在创建Figure时,根据不同的模型,创建了不同的Figure,开始活动的Figure为Ellipse(椭圆),普通活动的Figure为RectangleFigure(矩形),结束活动的Figure为Triangle(三角形),这个类我们也先定义到这儿。
下面我们要定转移模型对应的控制器,代码如下:
这个类继承的父类是AbstractConnectionEditPart,其实这个类的父类就是AbstractConnectionEditPart。我们只介绍createFigure方法,它为转移模型建一个带箭头的连线,并且设置箭头在目标节点端。
这样,我们就把模型对应的控制器和视图(Figure)都建完了,但有个问题,我们在控制器中只是调要父类的getModel()方法,来得到该控制器对应的模型,但gef框架是怎么知道我们模型和控制器的对应关系的呢,要让gef框架知道模型和控制器的对应关系,我们还必须建一个类,来建立模型和控制器的映射,代码如下:
我们必须把这个类注册到编辑器中,才可以让gef框架知道模型和控制器的映射关系,下一个我们将介绍编辑器方面的内容。
在控制器生效时,应该把控制器注册为对应模型的侦听器,为此我们应该覆盖父类的activate方法,代码如下:
public
void
activate()
{
if (!isActive()) {
super.activate(); ((ModelElement)getModel()).addPropertyChangeListener(this);
}
}
if (!isActive()) {
super.activate(); ((ModelElement)getModel()).addPropertyChangeListener(this);
}
}
同时在控制器失效时,我们从模型中删除这个侦听器,代码如下:
public
void
deactivate()
{
if (isActive()) {
super.deactivate();
((ModelElement) getModel()).removePropertyChangeListener(this);
}
}
if (isActive()) {
super.deactivate();
((ModelElement) getModel()).removePropertyChangeListener(this);
}
}
此外由于流程控制器对应的模型,里面包含了一组活动模型,所以我们还应该覆盖父类的getModelChildren(),代码如下:
private
WorkflowProcess getCastedModel()
{
return (WorkflowProcess) getModel();
}
protected List getModelChildren() {
return getCastedModel().getChildren();
}
return (WorkflowProcess) getModel();
}
protected List getModelChildren() {
return getCastedModel().getChildren();
}
我们知道控制器要根据模型的变化来刷新模型对应的视图,在gef框架中视图这部分是有draw2d中的Figure来实现的,由于这里的视图都比较简单,我们不再创建视图类了,直接引用draw2d自带的一些简单Figure,如果要实现复杂的视图,可以单独定义。这里我们覆盖createFigure方法,代码如下:
protected
IFigure createFigure()
{
Figure f = new FreeformLayer();
f.setLayoutManager(new FreeformLayout());
return f;
}
Figure f = new FreeformLayer();
f.setLayoutManager(new FreeformLayout());
return f;
}
这个Figure可以向四周无限扩展,相当与一块画布一样。流程控制器的类我们先定义到这儿,到以后还要修改这个类,来实现一些功能。完整代码如下:
package
com.example.workflow.parts;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import org.eclipse.draw2d.ConnectionLayer;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FreeformLayer;
import org.eclipse.draw2d.FreeformLayout;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.ShortestPathConnectionRouter;
import org.eclipse.gef.LayerConstants;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import com.example.workflow.model.ModelElement;
import com.example.workflow.model.WorkflowProcess;
public class WorkflowProcessEditPart extends AbstractGraphicalEditPart
implements PropertyChangeListener {
public void activate() {
if (!isActive()) {
super.activate();
((ModelElement) getModel()).addPropertyChangeListener(this);
}
}
public void deactivate() {
if (isActive()) {
super.deactivate();
((ModelElement) getModel()).removePropertyChangeListener(this);
}
}
private WorkflowProcess getCastedModel() {
return (WorkflowProcess) getModel();
}
/**//* (non-Javadoc)
* @see org.eclipse.gef.editparts.AbstractEditPart#getModelChildren()
*/
protected List getModelChildren() {
return getCastedModel().getChildren(); // return a list of activities
}
protected IFigure createFigure() {
Figure f = new FreeformLayer();
f.setLayoutManager(new FreeformLayout());
return f;
}
protected void createEditPolicies() {
// TODO Auto-generated method stub
}
public void propertyChange(PropertyChangeEvent arg0) {
// TODO Auto-generated method stub
}
}
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import org.eclipse.draw2d.ConnectionLayer;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FreeformLayer;
import org.eclipse.draw2d.FreeformLayout;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.ShortestPathConnectionRouter;
import org.eclipse.gef.LayerConstants;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import com.example.workflow.model.ModelElement;
import com.example.workflow.model.WorkflowProcess;
public class WorkflowProcessEditPart extends AbstractGraphicalEditPart
implements PropertyChangeListener {
public void activate() {
if (!isActive()) {
super.activate();
((ModelElement) getModel()).addPropertyChangeListener(this);
}
}
public void deactivate() {
if (isActive()) {
super.deactivate();
((ModelElement) getModel()).removePropertyChangeListener(this);
}
}
private WorkflowProcess getCastedModel() {
return (WorkflowProcess) getModel();
}
/**//* (non-Javadoc)
* @see org.eclipse.gef.editparts.AbstractEditPart#getModelChildren()
*/
protected List getModelChildren() {
return getCastedModel().getChildren(); // return a list of activities
}
protected IFigure createFigure() {
Figure f = new FreeformLayer();
f.setLayoutManager(new FreeformLayout());
return f;
}
protected void createEditPolicies() {
// TODO Auto-generated method stub
}
public void propertyChange(PropertyChangeEvent arg0) {
// TODO Auto-generated method stub
}
}
下面我们定义活动对应的控制器,活动虽然有开始活动,普通活动,结束活动,有不同视图(Figure),但控制器我们只需定义一个,在这个类中,我们再根据不同活动模型创建不同的Figure。完整代码如下:
package
com.example.workflow.parts;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Ellipse;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.RectangleFigure;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import com.example.workflow.model.Activity;
import com.example.workflow.model.EndActivity;
import com.example.workflow.model.ModelElement;
import com.example.workflow.model.StartActivity;
public class AbstractActivityEditPart extends AbstractGraphicalEditPart
implements PropertyChangeListener {
public void activate() {
if (!isActive()) {
super.activate();
((ModelElement) getModel()).addPropertyChangeListener(this);
}
}
protected IFigure createFigure() {
IFigure f = createFigureForModel();
f.setOpaque(true); // 图形不透明
f.setBackgroundColor(ColorConstants.green);//背景色为绿色
return f;
}
private IFigure createFigureForModel() {
if (getModel() instanceof StartActivity) {
return new Ellipse();//椭圆
}else if (getModel() instanceof EndActivity) {
return new Triangle();//三角形
} else if (getModel() instanceof Activity) {
return new RectangleFigure();//矩形
} else {
throw new IllegalArgumentException();
}
}
public void deactivate() {
if (isActive()) {
super.deactivate();
((ModelElement) getModel()).removePropertyChangeListener(this);
}
}
protected void createEditPolicies() {
// TODO Auto-generated method stub
}
public void propertyChange(PropertyChangeEvent arg0) {
// TODO Auto-generated method stub
}
}
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Ellipse;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.RectangleFigure;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import com.example.workflow.model.Activity;
import com.example.workflow.model.EndActivity;
import com.example.workflow.model.ModelElement;
import com.example.workflow.model.StartActivity;
public class AbstractActivityEditPart extends AbstractGraphicalEditPart
implements PropertyChangeListener {
public void activate() {
if (!isActive()) {
super.activate();
((ModelElement) getModel()).addPropertyChangeListener(this);
}
}
protected IFigure createFigure() {
IFigure f = createFigureForModel();
f.setOpaque(true); // 图形不透明
f.setBackgroundColor(ColorConstants.green);//背景色为绿色
return f;
}
private IFigure createFigureForModel() {
if (getModel() instanceof StartActivity) {
return new Ellipse();//椭圆
}else if (getModel() instanceof EndActivity) {
return new Triangle();//三角形
} else if (getModel() instanceof Activity) {
return new RectangleFigure();//矩形
} else {
throw new IllegalArgumentException();
}
}
public void deactivate() {
if (isActive()) {
super.deactivate();
((ModelElement) getModel()).removePropertyChangeListener(this);
}
}
protected void createEditPolicies() {
// TODO Auto-generated method stub
}
public void propertyChange(PropertyChangeEvent arg0) {
// TODO Auto-generated method stub
}
}
在这个类中activate,deactivate方法功能和流程控制器中一样,只是在创建Figure时,根据不同的模型,创建了不同的Figure,开始活动的Figure为Ellipse(椭圆),普通活动的Figure为RectangleFigure(矩形),结束活动的Figure为Triangle(三角形),这个类我们也先定义到这儿。
下面我们要定转移模型对应的控制器,代码如下:
package
com.example.workflow.parts;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.PolygonDecoration;
import org.eclipse.draw2d.PolylineConnection;
import org.eclipse.gef.editparts.AbstractConnectionEditPart;
import com.example.workflow.model.ModelElement;
public class TransitionEditPart extends AbstractConnectionEditPart
implements PropertyChangeListener {
public void activate() {
if (!isActive()) {
super.activate();
((ModelElement) getModel()).addPropertyChangeListener(this);
}
}
/**//* (non-Javadoc)
* @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
*/
protected IFigure createFigure() {
PolylineConnection connection = (PolylineConnection) super.createFigure();
connection.setTargetDecoration(new PolygonDecoration()); //箭头在目标节点
return connection;
}
public void deactivate() {
if (isActive()) {
super.deactivate();
((ModelElement) getModel()).removePropertyChangeListener(this);
}
}
protected void createEditPolicies() {
// TODO Auto-generated method stub
}
public void propertyChange(PropertyChangeEvent arg0) {
// TODO Auto-generated method stub
}
}
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.PolygonDecoration;
import org.eclipse.draw2d.PolylineConnection;
import org.eclipse.gef.editparts.AbstractConnectionEditPart;
import com.example.workflow.model.ModelElement;
public class TransitionEditPart extends AbstractConnectionEditPart
implements PropertyChangeListener {
public void activate() {
if (!isActive()) {
super.activate();
((ModelElement) getModel()).addPropertyChangeListener(this);
}
}
/**//* (non-Javadoc)
* @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
*/
protected IFigure createFigure() {
PolylineConnection connection = (PolylineConnection) super.createFigure();
connection.setTargetDecoration(new PolygonDecoration()); //箭头在目标节点
return connection;
}
public void deactivate() {
if (isActive()) {
super.deactivate();
((ModelElement) getModel()).removePropertyChangeListener(this);
}
}
protected void createEditPolicies() {
// TODO Auto-generated method stub
}
public void propertyChange(PropertyChangeEvent arg0) {
// TODO Auto-generated method stub
}
}
这个类继承的父类是AbstractConnectionEditPart,其实这个类的父类就是AbstractConnectionEditPart。我们只介绍createFigure方法,它为转移模型建一个带箭头的连线,并且设置箭头在目标节点端。
这样,我们就把模型对应的控制器和视图(Figure)都建完了,但有个问题,我们在控制器中只是调要父类的getModel()方法,来得到该控制器对应的模型,但gef框架是怎么知道我们模型和控制器的对应关系的呢,要让gef框架知道模型和控制器的对应关系,我们还必须建一个类,来建立模型和控制器的映射,代码如下:
package
com.example.workflow.parts;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartFactory;
import com.example.workflow.model.AbstractActivity;
import com.example.workflow.model.Transition;
import com.example.workflow.model.WorkflowProcess;
public class WorkflowProcessEditPartFactory implements EditPartFactory {
public EditPart createEditPart(EditPart context, Object modelElement) {
// get EditPart for model element
EditPart part = getPartForElement(modelElement);
// store model element in EditPart
part.setModel(modelElement);
return part;
}
/** *//**
* Maps an object to an EditPart.
* @throws RuntimeException if no match was found (programming error)
*/
private EditPart getPartForElement(Object modelElement) {
if (modelElement instanceof WorkflowProcess) {
return new WorkflowProcessEditPart();
}
if (modelElement instanceof AbstractActivity) {
return new AbstractActivityEditPart();
}
if (modelElement instanceof Transition) {
return new TransitionEditPart();
}
throw new RuntimeException(
"Can't create part for model element: "
+ ((modelElement != null) ? modelElement.getClass().getName() : "null"));
}
}
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartFactory;
import com.example.workflow.model.AbstractActivity;
import com.example.workflow.model.Transition;
import com.example.workflow.model.WorkflowProcess;
public class WorkflowProcessEditPartFactory implements EditPartFactory {
public EditPart createEditPart(EditPart context, Object modelElement) {
// get EditPart for model element
EditPart part = getPartForElement(modelElement);
// store model element in EditPart
part.setModel(modelElement);
return part;
}
/** *//**
* Maps an object to an EditPart.
* @throws RuntimeException if no match was found (programming error)
*/
private EditPart getPartForElement(Object modelElement) {
if (modelElement instanceof WorkflowProcess) {
return new WorkflowProcessEditPart();
}
if (modelElement instanceof AbstractActivity) {
return new AbstractActivityEditPart();
}
if (modelElement instanceof Transition) {
return new TransitionEditPart();
}
throw new RuntimeException(
"Can't create part for model element: "
+ ((modelElement != null) ? modelElement.getClass().getName() : "null"));
}
}
我们必须把这个类注册到编辑器中,才可以让gef框架知道模型和控制器的映射关系,下一个我们将介绍编辑器方面的内容。