posts - 36, comments - 30, trackbacks - 0, articles - 3
                這一節(jié)我們來介紹如何在編輯器中移動(dòng)活動(dòng),改變活動(dòng)的大小和刪除活動(dòng),在流程控制器中已經(jīng)安裝的策略WorkflowProcessXYLayoutEditPolicy,可以接受移動(dòng)活動(dòng)和改變活動(dòng)大小的請(qǐng)求,但不能接受刪除活動(dòng)的請(qǐng)求,要處理刪除活動(dòng)的請(qǐng)求,必須在活動(dòng)控制器中安裝策略。

                 我們還是先來看WorkflowProcessXYLayoutEditPolicy這個(gè)類,要實(shí)現(xiàn)改變活動(dòng)大小和位置的功能,應(yīng)該覆蓋父類的createChangeConstraintCommand方法,具體代碼如下:

          /**ResizeorMoveAbstractActivityintheWorkflowProcessEditor*/
              
          protected Command createChangeConstraintCommand(ChangeBoundsRequest request, EditPart child, Object constraint) {
                 
          if(child instanceof AbstractActivityEditPart && constraint instanceof Rectangle){
                     
          //return a command that can move and/or resize a AbstractActivity
                     returnnew AbstractActivitySetConstraintCommand(
                             (AbstractActivity)child.getModel(), request, (Rectangle) constraint);
                 }

                 returnsuper.createChangeConstraintCommand(request, child, constraint);
              }
           

          在這個(gè)方法中,我們創(chuàng)建一個(gè)AbstractActivitySetConstraintCommand命令,用這個(gè)命令來修改活動(dòng)的位置,大小屬性,這個(gè)命令的具體代碼如下:

          package com.example.workflow.commands;
           
          import org.eclipse.draw2d.geometry.Rectangle;
          import org.eclipse.gef.RequestConstants;
          import org.eclipse.gef.commands.Command;
          import org.eclipse.gef.requests.ChangeBoundsRequest;
           
          import com.example.workflow.model.AbstractActivity;
           
          /**
           * A command to resize and/or move a shape.
           * The command can be undone or redone. 
           
          */

          public class AbstractActivitySetConstraintCommand extends Command{
                 
                 
          /** Stores the new size and location. */
                 
          private final Rectangle newBounds;
                 
          /** Stores the old size and location. */
                 
          private Rectangle oldBounds;
                 
          /** A request to move/resize an edit part. */
                 
          private final ChangeBoundsRequest request;
                 
                 
          /** AbstractActivity to manipulate. */
                 
          private final AbstractActivity abstractActivity;
                 
                 
          /**
                  * Create a command that can resize and/or move a AbstractActivity. 
                  * 
          @param abstractActivity the AbstractActivity to manipulate
                  * 
          @param req             the move and resize request
                  * 
          @param newBounds the new size and location
                  * 
          @throws IllegalArgumentException if any of the parameters is null
                  
          */

                 
          public AbstractActivitySetConstraintCommand(AbstractActivity abstractActivity,
                               ChangeBoundsRequest req,Rectangle newBounds)
          {
                        
          if (abstractActivity == null || req == null || newBounds == null{
                               
          throw new IllegalArgumentException();
                        }

                        
          this.abstractActivity = abstractActivity;
                        
          this.request = req;
                        
          this.newBounds = newBounds.getCopy();
                        setLabel(
          "move / resize");
                 }

                 
                 
          /* (non-Javadoc)
                  * @see org.eclipse.gef.commands.Command#canExecute()
                  
          */

                 
          public boolean canExecute() {
                        Object type 
          = request.getType();
                        
          // make sure the Request is of a type we support:
                        return (RequestConstants.REQ_MOVE.equals(type)
                                      
          || RequestConstants.REQ_MOVE_CHILDREN.equals(type) 
                                      
          || RequestConstants.REQ_RESIZE.equals(type)
                                      
          || RequestConstants.REQ_RESIZE_CHILDREN.equals(type));
                 }

                 
                 
          /* (non-Javadoc)
                  * @see org.eclipse.gef.commands.Command#execute()
                  
          */

                 
          public void execute() {
                        oldBounds 
          = new Rectangle(abstractActivity.getLocation(), abstractActivity.getSize());
                        redo();
                 }

           
                 
          /* (non-Javadoc)
                  * @see org.eclipse.gef.commands.Command#redo()
                  
          */

                 
          public void redo() {
                        abstractActivity.setSize(newBounds.getSize());
                        abstractActivity.setLocation(newBounds.getLocation());
                 }

           
                 
          /* (non-Javadoc)
                  * @see org.eclipse.gef.commands.Command#undo()
                  
          */

                 
          public void undo() {
                        abstractActivity.setSize(oldBounds.getSize());
                        abstractActivity.setLocation(oldBounds.getLocation());
                 }

           
          }

          我們知道修改了活動(dòng)的大小,位置屬性之后,活動(dòng)模型會(huì)通知控制器它的LOCATION_PROP,SIZE_PROP發(fā)生變化,這可在模型的定義中看到:

          publicvoid setLocation(Point newLocation) {
                 
          if (newLocation == null{
                     thrownew IllegalArgumentException();
                 }

                 location.setLocation(newLocation);
                 firePropertyChange(LOCATION_PROP, 
          null, location);
              }

              
              
              publicvoid setSize(Dimension newSize) 
          {
                 
          if (newSize != null{
                     size.setSize(newSize);
                     firePropertyChange(SIZE_PROP, 
          null, size);
                 }

              }

          活動(dòng)控制器AbstractActivityEditPart應(yīng)該根據(jù)這些屬性的變化來刷新視圖,代碼如下:
          publicvoid propertyChange(PropertyChangeEvent evt) {
                 String prop 
          = evt.getPropertyName();      
                 
          if(AbstractActivity.SIZE_PROP.equals(prop) 
                        
          ||AbstractActivity.LOCATION_PROP.equals(prop)){
                     refreshVisuals();
                 }
                
              }

          而refreshVisuals()方法我們已經(jīng)在前面實(shí)現(xiàn)好了,這樣我們運(yùn)行項(xiàng)目,就可以改變活動(dòng)的位置和大小了,


          接下來,我們介紹如何在編輯器中刪除活動(dòng),要實(shí)現(xiàn)這功能,應(yīng)該在活動(dòng)控制器AbstractActivityEditPart中安裝能接受刪除活動(dòng)請(qǐng)求的策略,代碼如下:

          protectedvoid createEditPolicies() {
                 
          //allow removal of the associated model element
                 installEditPolicy(EditPolicy.COMPONENT_ROLE, new AbstractActivityComponentEditPolicy());
                 
              }


          策略AbstractActivityComponentEditPolicy的代碼如下:

          package com.example.workflow.policy;
           
          import org.eclipse.gef.commands.Command;
          import org.eclipse.gef.editpolicies.ComponentEditPolicy;
          import org.eclipse.gef.requests.GroupRequest;
           
          import com.example.workflow.commands.AbstractActivityDeleteCommand;
          import com.example.workflow.model.AbstractActivity;
          import com.example.workflow.model.WorkflowProcess;
           
           
          public class AbstractActivityComponentEditPolicy extends ComponentEditPolicy{
           
                 
          protected Command createDeleteCommand(GroupRequest deleteRequest) {
                        Object parent 
          = getHost().getParent().getModel();
                        Object child 
          = getHost().getModel();
                        
          if(parent instanceof WorkflowProcess && child instanceof AbstractActivity){
                               
          return new AbstractActivityDeleteCommand((WorkflowProcess)parent,(AbstractActivity)child);
                        }

                        
          return super.createDeleteCommand(deleteRequest);
                 }

           
          }

          這個(gè)策略繼承了ComponentEditPolicy類,并且覆蓋了createDeleteCommand方法,在這個(gè)方法中,我們創(chuàng)建了AbstractActivityDeleteCommand命令,這個(gè)命令完成從流程模型中刪除當(dāng)前活動(dòng)模型,我們知道在活動(dòng)模型中,還維護(hù)著輸入轉(zhuǎn)移和輸出轉(zhuǎn)移兩個(gè)列表,而轉(zhuǎn)移對(duì)象中又維護(hù)著轉(zhuǎn)移的起始活動(dòng)和終止活動(dòng),由于刪除了活動(dòng),轉(zhuǎn)移就成了只有源點(diǎn)或者只要目標(biāo)點(diǎn),因此,我們還應(yīng)該從還維護(hù)著這些轉(zhuǎn)移的活動(dòng)中刪除這些轉(zhuǎn)移,該命令的代碼如下:

          package com.example.workflow.commands;
           
          import java.util.Iterator;
          import java.util.List;
           
          import org.eclipse.gef.commands.Command;
           
          import com.example.workflow.model.AbstractActivity;
          import com.example.workflow.model.Transition;
          import com.example.workflow.model.WorkflowProcess;
           
           
          /**
           * A command to remove a AbstractActivity from its parent.
           * The command can be undone or redone.
           
          */

          public class AbstractActivityDeleteCommand extends Command{
                 
                 
          /** AbstractActivity to remove. */
                 
          private final AbstractActivity child;
                 
          /** WorkflowProcess to remove from. */
                 
          private final WorkflowProcess parent;
                 
          /** Holds a copy of the outgoing transitions of child. */
                 
          private List sourceTransitions;
                 
          /** Holds a copy of the incoming transitions of child. */
                 
          private List targetTransitions;
                 
          /** True, if child was removed from its parent. */
                 
          private boolean wasRemoved;
           
                 
          /**
                  * Create a command that will remove the AbstractActivity from its parent.
                  * 
          @param parent the WorkflowProcess containing the child
                  * 
          @param child    the AbstractActivity to remove
                  * 
          @throws IllegalArgumentException if any parameter is null
                  
          */

                 
          public AbstractActivityDeleteCommand(WorkflowProcess parent, AbstractActivity child) {
                        
          if (parent == null || child == null{
                               
          throw new IllegalArgumentException();
                        }

                        setLabel(
          "activity deletion");
                        
          this.parent = parent;
                        
          this.child = child;
                 }

           
                 
          /**
                  * Reconnects a List of Transitions with their previous endpoints.
                  * 
          @param transitions a non-null List of connections
                  
          */

                 
          private void addConnections(List transitions) {
                        
          for (Iterator iter = transitions.iterator(); iter.hasNext();) {
                               Transition tran 
          = (Transition) iter.next();
                               tran.reconnect();
                        }

                 }

           
                 
          /* (non-Javadoc)
                  * @see org.eclipse.gef.commands.Command#canUndo()
                  
          */

                 
          public boolean canUndo() {
                        
          return wasRemoved;
                 }

           
                 
          /* (non-Javadoc)
                  * @see org.eclipse.gef.commands.Command#execute()
                  
          */

                 
          public void execute() {
                        
          // store a copy of incoming & outgoing transitions before proceeding 
                        sourceTransitions = child.getSourceTransitions();
                        targetTransitions 
          = child.getTargetTransitions();
                        redo();
                 }

           
                 
          /* (non-Javadoc)
                  * @see org.eclipse.gef.commands.Command#redo()
                  
          */

                 
          public void redo() {
                        
          // remove the child and disconnect its connections
                        wasRemoved = parent.removeChild(child);
                        
          if (wasRemoved) {
                               removeTransitions(sourceTransitions);
                               removeTransitions(targetTransitions);
                        }

                 }

           
                 
          /**
                  * Disconnects a List of Transitions from their endpoints.
                  * 
          @param transitions a non-null List of transitions
                  
          */

                 
          private void removeTransitions(List transitions) {
                        
          for (Iterator iter = transitions.iterator(); iter.hasNext();) {
                               Transition tran 
          = (Transition) iter.next();
                               tran.disconnect();
                        }

                 }

           
                 
          /* (non-Javadoc)
                  * @see org.eclipse.gef.commands.Command#undo()
                  
          */

                 
          public void undo() {
                        
          // add the child and reconnect its transitions
                        if (parent.addChild(child)) {
                               addConnections(sourceTransitions);
                               addConnections(targetTransitions);
                        }

                 }

          }

          這個(gè)命令中從流程模型中刪除了活動(dòng)模型,流程模型通知控制器,它的CHILD_REMOVED_PROP屬性發(fā)生了變化,要控制器刷新它維護(hù)的活動(dòng)集。
          要實(shí)現(xiàn)刪除操作,我們必須通過刪除菜單或者鍵盤的刪除鍵,但現(xiàn)在編輯器還不支持這些功能,無論是通過刪除菜單還是刪除鍵,都是執(zhí)行了一個(gè)Action,由這個(gè)Action來執(zhí)行我們定義的刪除命令(關(guān)于Action和菜單的實(shí)現(xiàn),我們?cè)谝院髸?huì)講),這兒只介紹如何讓編輯器支持鍵盤操作,要實(shí)現(xiàn)鍵盤操作,在WorkflowProcessEditor類中定義一個(gè)KeyHandler 類型的成員變量sharedKeyHandler;
          接下來定義一個(gè)方法:

          protected KeyHandler getCommonKeyHandler() {
              
          if (sharedKeyHandler == null{
                 sharedKeyHandler 
          = new KeyHandler();
                 sharedKeyHandler.put(
                     KeyStroke.getPressed(SWT.DEL, 
          1270),
                     getActionRegistry().getAction(ActionFactory.DELETE.getId()));      
              }

              returnsharedKeyHandler;
          }

          該方法的作用是定義我們支持的鍵名,上面定義了刪除鍵,并且把這個(gè)鍵和刪除Action邦定,當(dāng)按刪除鍵,就執(zhí)行對(duì)應(yīng)的Action,sharedKeyHandler可以供編輯器和大綱視圖公用,關(guān)于大綱視圖在以后會(huì)講。
          接下來還需要在編輯器視圖中注冊(cè)這些這些公共鍵,代碼如下:
          protectedvoid configureGraphicalViewer() {      
                 
          super.configureGraphicalViewer();
                 GraphicalViewer viewer 
          = getGraphicalViewer();
                 viewer.setEditPartFactory(
          new WorkflowProcessEditPartFactory());
                 viewer.setRootEditPart(
          new ScalableFreeformRootEditPart());
                 
                 getGraphicalViewer().setKeyHandler(
          new GraphicalViewerKeyHandler(getGraphicalViewer())
                 .setParent(getCommonKeyHandler()));
              }
            

          這樣運(yùn)行項(xiàng)目,我們就可以用鍵盤的刪除鍵來刪除活動(dòng)了,我們注意到無論我們向編輯器中增加活動(dòng),還是刪除活動(dòng),編輯器的狀態(tài)始終沒變,不像其它編輯器修改之后,提示編輯器處于未保存狀態(tài),我們要實(shí)現(xiàn)這個(gè)功能其實(shí)很簡(jiǎn)單,只需在WorkflowProcessEditor類中覆蓋父類的方法commandStackChanged,代碼如下:
          publicvoid commandStackChanged(EventObject event) {
                 firePropertyChange(IEditorPart.PROP_DIRTY);
                 
          super.commandStackChanged(event);
              }

          其實(shí)這個(gè)方法的原理很簡(jiǎn)單,當(dāng)編輯器的命令堆棧發(fā)生改變時(shí),修改編輯器狀態(tài)為未保存。我們知道我們進(jìn)行增加活動(dòng),刪除活動(dòng)等操作時(shí),都是執(zhí)行了一個(gè)個(gè)命令,而這些命令都保存在編輯器的命令堆棧里,所以我們每執(zhí)行一個(gè)命令,編輯器的命令堆棧就發(fā)生改變。
          再運(yùn)行項(xiàng)目,我們就可以看到在編輯器處于已保存狀態(tài)時(shí),我們?cè)龠M(jìn)行操作,例如增加活動(dòng),刪除活動(dòng),編輯器的狀態(tài)就變成未保存了,至于在未保存狀態(tài),點(diǎn)保存按鈕,還是未保存,這在以后,我們會(huì)解決。下一節(jié),我們將介紹如何在活動(dòng)之間增加和刪除轉(zhuǎn)移,如何在轉(zhuǎn)移上增加拐點(diǎn)。
          主站蜘蛛池模板: 都兰县| 冷水江市| 灵丘县| 绥江县| 龙山县| 固安县| 大邑县| 嘉义县| 诸城市| 荥经县| 洪雅县| 腾冲县| 旺苍县| 汉寿县| 隆安县| 玉山县| 洞头县| 霍州市| 泾阳县| 蒙阴县| 巍山| 惠东县| 武穴市| 土默特左旗| 石狮市| 时尚| 云龙县| 松阳县| 南岸区| 孝义市| 玛沁县| 福建省| 衡东县| 阿克陶县| 镇江市| 成都市| 宝鸡市| 基隆市| 永宁县| 游戏| 乌苏市|