流程設計器開發一(控制器和視圖部分)

 
       這一節,我們講控制器的設計,在gef框架中,控制器作爲連接模型和視圖的橋樑,它主要根據用戶的操作來修改模型,並且刷新視圖。在前面我們定義了流程模型(WorkflowProcess),活動模型(AbstractActivity),轉移模型(Transition),在這裏我們分別定義相應的控制器(EditPart),首先我們定義流程模型對應的控制器(WorkflowProcessEditPart),每個控制器都必須繼承AbstractGraphicalEditPart類,並且由於控制器要作爲模型的偵聽器,偵聽模型的變化,所以它還必須實現PropertyChangeListener接口。
在控制器生效時,應該把控制器註冊爲對應模型的偵聽器,爲此我們應該覆蓋父類的activate方法,代碼如下:
publicvoid activate() {
       if (!isActive()) {
           super.activate();        ((ModelElement)getModel()).addPropertyChangeListener(this);
       }
    }
同時在控制器失效時,我們從模型中刪除這個偵聽器,代碼如下:
publicvoid deactivate() {
       if (isActive()) {
           super.deactivate();
           ((ModelElement) getModel()).removePropertyChangeListener(this);
       }
    }
此外由於流程控制器對應的模型,裏面包含了一組活動模型,所以我們還應該覆蓋父類的getModelChildren(),代碼如下:
   //該方法可以得到控制器對應的模型
private WorkflowProcess getCastedModel() {
       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可以向四周無限擴展,相當與一塊畫布一樣。流程控制器的類我們先定義到這兒,到以後還要修改這個類,來實現一些功能。完整代碼如下:
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
             
       }
      
      
}
 
下面我們定義活動對應的控制器,活動雖然有開始活動,普通活動,結束活動,有不同視圖(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
             
       }
       }
在這個類中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
             
       }
 
}
這個類繼承的父類是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"));
       }
 
 
}
 
我們必須把這個類註冊到編輯器中,纔可以讓gef框架知道模型和控制器的映射關係,下一個我們將介紹編輯器方面的內容。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章