精彩的人生

          好好工作,好好生活

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            147 Posts :: 0 Stories :: 250 Comments :: 0 Trackbacks
          這是本人原創作品,如有轉載,請注明出處。

           

          前面的那篇文章emf&gef之一example.my.gefpractice講述的是如何將emfgef結合起來使用。

          在實際的項目開發中模型的是根據需求來定的,可以說模型事實上是業務邏輯。聲明這一點是為了說明本文研究內容的必要性。

          前面的文章中使用的模型定義,包含x,y,w,h(他們確定了編輯器的一個矩形區域,這個矩形區域用來顯示模型的圖像),除此之外還包含了一個connection對象,每個nodeinputsoutputs

          簡單的說,前文中的模型是從編輯器的角度來定義模型的。

          假如從業務的角度來看,模型之間的關系是什么樣的呢?

          假如從業務上來看,node之間只有一個next關系,來表明先后順序。

           

          定義模型

           

          根據上面的分析,從新定義模型,如下圖所示:

          emfgef2_1.JPG

          第一篇文章中定義的模型,編輯器內容序列化為xml文件格式為:

          <Diagram>
          <Node >
              
          <Connection />
          </Node>
          </Diagram>

          那么本文中的格式為

          <Diagram>
          <Node name=”node0” next=”node1”/>
          <Node name
          =”node1”/>
          </Diagram>

           

          創建工程

          與前面的文章一樣,利用這個ecore文件創建EMF Project,并根據生成的genmodel文件生成模型代碼。

           

          事件監聽

              也與前面的文章一樣,對每個模型創建一個對應的PropertySource文件,在EditPart中將PropertySource安裝給模型,并在EditPart中監聽模型更改事件,做相應處理。

           

          編輯器

           

          對模型而言,Connection對象是可有可無的,但是對編輯器而言,沒有了Connection對象,如何創建連線對象呢?

          所以我們需要寫Connection對象,這個對象只在GEF框架下使用,用來描述兩個節點間的next關系,不寫入xml文件。

           

          Connection.java

          public class Connection {
              
          protected Node source = null
          ;
              
          protected Node target = null
          ;
              
          public Connection() 
          {
              }

              
              
          public Node getSource() {
                  
          return
           source;
              }

              
              
          public void setSource(Node newSource) {
                  source 
          =
           newSource;
              }


              
          public Node getTarget() {
                  
          return
           target;
              }


              
          public void setTarget(Node newTarget) {
                  target 
          =
           newTarget;
              }


          }

           

          有了 Connection對象,并不代表就能正確使用它。

           

          首先,在NodeEditPart中定義兩個變量以及相應的get方法

           

          NodesEditPart.java

          ……
          private
           ArrayList sourceConnections;
              
          private
           ArrayList targetConnections;
              ……
          public List getModelSourceConnections() 
          {
                  
          if(this.sourceConnections==null
          )
                      
          this.sourceConnections = new
           ArrayList();
                  
          return
           sourceConnections;
              }

              
          public List getModelTargetConnections() {
                  
          if(this.targetConnections==null
          )
                      
          this.targetConnections = new
           ArrayList();
                  
          return
           targetConnections;
              }

          ……

           

          接著在ConnectionCreateCommand中,在執行這個命令的時候,給nodenext屬性賦值:

          public void execute() {
                  connection 
          = new
           Connection();
                  connection.setSource(source);
                  connection.setTarget(target);
                  sourcePart.getModelTargetConnections().add(connection);
                  targetPart.getModelSourceConnections().add(connection);
                  
                  source.getNext().add(target);
          //模型屬性改變,會刷新相關的對象

                  targetPart.refresh();//模型沒有改變,手工要求刷新
          }

           

          以上僅完成了創建一個Connection,完成了給Nodenext賦值。保存編輯器內容,可以查看一下結果。

           

              假如重新打開剛剛保存的文件,發現問題了嗎?連線對象消失了。

                 為什么呢?看看NodesEditPartFactory#createEditPart你會有收獲的。

           

              EMFxml文件反序列化為了一個數據結構,很明顯,這個數據結構中沒有Connection對象。GEF將按照這個數據結構提供的模型來初始化編輯器內容,那么當然會丟失連線。

           

              解決方法:創建一個TargetAddConnectionTable,它用來保存未完成的連線。

           

          NodesEditPartFactory.java

          private EditPart getPartForElement(Object modelElement) {
                  
          if (modelElement instanceof Diagram) 
          {
                      
          return new
           DiagramEditPart();
                  }

                  
          if (modelElement instanceof Node) {
                      NodesEditPart nep 
          = new
           NodesEditPart();
                      
                      
          //add target connections

                      if(TargetAddConnectionTable.getInstance().contains((Node) modelElement)){
                          List l 
          =
           TargetAddConnectionTable.getInstance().getValue((Node) modelElement);
                          
          if(l!=null && l.size()>0)
          {
                              
          for(int i=0; i<l.size(); i++)
          {
                                  Connection c 
          =
           (Connection) l.get(i);
                                  nep.getModelSourceConnections().add(c);
                                  TargetAddConnectionTable.getInstance().remove(c);
                              }

                          }

                      }

                      
                      
          //add source connections
                      List l = ((Node)modelElement).getNext();
                      
          if(l!=null && l.size()>0)
          {
                          
          for(int i=0; i<l.size(); i++)
          {
                              Connection c 
          = new
           Connection();
                              c.setSource((Node) modelElement);
                              c.setTarget((Node) l.get(i));
                              nep.getModelTargetConnections().add(c);
                              TargetAddConnectionTable.getInstance().add(c, c.getTarget());
                          }

                      }

                      
                      
          return nep;
                  }

                  
          if (modelElement instanceof Connection) {
                      
          return new
           ConnectionEditPart();
                  }

                  
          throw new RuntimeException(
                          
          "Can't create part for model element: "

                          
          + ((modelElement != null? modelElement.getClass().getName() : "null"));
              }

           

          TargetAddConnectionTable.java

          public class TargetAddConnectionTable {
              
          private Hashtable hs = null
          ;
              
          private static TargetAddConnectionTable table=null
          ;
              
              
          private TargetAddConnectionTable()
          {
                      hs
          =new
           Hashtable();
              }

              
              
          public static TargetAddConnectionTable getInstance(){
                  
          if(table==null
          )
                      table 
          = new
           TargetAddConnectionTable();
                  
          return
           table;
              }

              
              
          public void add(Connection connection, Node target ){
                  hs.put( connection, target );
              }

              
              
          public void remove(Connection connection){
                  hs.remove(connection);
              }

              
              
          public boolean contains(Node target){
                  
          return
           hs.containsValue(target);
              }

              
              
          public List getValue(Node target){
                  ArrayList result 
          = new
           ArrayList();
                  Enumeration em 
          =
           hs.keys();
                  Connection c 
          = null
          ;
                  
          while(em.hasMoreElements())
          {
                      c 
          =
           (Connection) em.nextElement();
                      
          if
          (hs.get(c).equals(target))
                          result.add(c);
                  }

                  
          return result;
              }


          }

           

          再試試打開xml文件,應該出現連線了。

           

          這里需要說明的是,由于本例比較簡單,TargetAddConnectionTable沒有出現太大問題。在實際應用中發現TergetAddConnectionTable有不足,也做過了更正。筆者在此不再修改代碼。假如讀者有興趣,可以測測問題是什么,問題產生的原因以及如何解決。

           

          其他

          本例依然采用兩個action來打開編輯器。

          本例的運行結果與前面的例子是一樣的,因為從編輯器的角度來看,沒有變化。

           

          源碼

           

          點擊下載

           

          運行環境

          JDK1.4

          Eclipse 3.1

          GEF

          EMF

           


          posted on 2005-12-15 13:44 hopeshared 閱讀(2707) 評論(0)  編輯  收藏 所屬分類: EMF&GEF
          主站蜘蛛池模板: 昌宁县| 和田市| 龙岩市| 兰溪市| 大埔县| 黄平县| 仙桃市| 桐城市| 汪清县| 杭锦旗| 佛坪县| 梅州市| 灵丘县| 东乡族自治县| 涞水县| 自治县| 内乡县| 温泉县| 内江市| 达拉特旗| 华蓥市| 密山市| 县级市| 磐安县| 溆浦县| 汉中市| 齐齐哈尔市| 吴忠市| 太原市| 乌什县| 泾源县| 措美县| 黄龙县| 布拖县| 祁东县| 广元市| 西平县| 新邵县| 偏关县| 三原县| 瑞昌市|