精彩的人生

          好好工作,好好生活

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            147 Posts :: 0 Stories :: 250 Comments :: 0 Trackbacks

          八進制寫的關于GEF以及EMF的文章,對我當時的工作幫助很大。

           

          我最初看的是他的關于GEF的文章,但是我的工作需要將GEFEMF結合,本文使用的例子就是根據八進制的Bloggefpractice改編而成。

           

           

          定義模型

           

          自從EMF出現以后,出現了一種新的說法:模型驅動的軟件開發(例如Marlin),經過這段時間的研究開發,發現使用GEFEMF確實是這樣,一旦模型定義好了,這個項目就基本定型了。

           

          Ok,廢話留著以后慢慢說,進入正題先。

           

          首先,定義模型。在gefpractice這個例子中,模型很簡單,只有三類元素:DiagramNodeConnection。他們之間的關系,用EMF的模型文件(ecore)定義出來就是這樣的:

          1.JPG

          在做模型定義的時候,需要注意他們之間的包含關系。打開Properties視圖,有一個
          2.JPG

          Containment屬性需要格外注意,因為它將決定該接點是一個屬性還是一個子節點。以上圖為例,這個屬性設置為true,那么xml文件的格式是

          <Diagram>

          <Node/>

          </Diagram>

           

          假如是false,那么就是

          <Diagram nodes=”//node.0”/>

          <Node />

           

          由于有這個問題,在定義Node的時候就一定要注意sourceConnectionstargetConnections的這個屬性,一個是true,另一個是false。(自己想想,為什么呢?^-^

           

          當然模型的定義并不是只有這種方式,只要你將邏輯表述對了,這個模型就沒有問題。

           

          創建工程

           

          用這個模型創建一個EMF Project。操作過程是New -> Project -> EMF Project -> 工程名稱是eclipse.my.gefpractice -> 選擇Ecore Model -> 選擇定義好的nodeemf.ecoreload -> 其他的按照默認選擇。這樣,你的工作區就創建了這個工程。

          這個新建的工程有個model文件夾,里面有nodeemf.ecorenodeemf.genmodel兩個文件。用當前默認的編輯器打開nodeemf.genmodel文件,更改根節點(Nodeemf)的子節點(nodeemf)的屬性(從屬性視圖中改)
          3.JPG

          接著,右鍵選擇上圖中的根節點,選擇Generate Model Code。這樣,模型的代碼就全部生成了。

           

          事件監聽

           

          一般,完全使用GEF的情況下,模型的監聽是通過模型實現PropertySource來實現的。詳細的請參看八進制的相關文章。但是本文中使用EMF來定義模型,那么原則上就不修改生成的代碼。那么,這里利用Adapter來給模型“安裝”屬性。

           

          這里給出一段示例代碼

          public class NodePropertySource extends AbstractPropertySource {
              
              
          private static final String ID_X = "X";
              
          private static final String ID_Y = "Y";
              
          private static final String ID_NAME = "Name";
              
          private static final String ID_VISIBLE = "Visible";
              
              
          public NodePropertySource(Object model) {
                  
          super(model);
              }

              
              
          private Node getNode() {
                  
          return (Node) getModel();
              }

              
              
          public void createPropertyDescriptors(List descriptors) {
                  descriptors.add(
          new TextPropertyDescriptor(ID_X, ID_X));
                  descriptors.add(
          new TextPropertyDescriptor(ID_Y, ID_Y));
                  descriptors.add(
          new TextPropertyDescriptor(ID_NAME, ID_NAME));
                  descriptors.add(
          new TextPropertyDescriptor(ID_VISIBLE, ID_VISIBLE));
              }

              
              
          public Object getPropertyValue(Object id) {
                  
          if(id == ID_X) {
                      
          return Integer.toString(getNode().getX());
                  }

                  
          if(id == ID_Y) {
                      
          return Integer.toString(getNode().getY());
                  }

                  
          if(id == ID_NAME) {
                      
          return getNode().getName();
                  }

                  
          if(id == ID_VISIBLE) {
                      
          return Boolean.toString(getNode().isVisible());
                  }

                  
          return null;
              }

              
              
          public void setPropertyValue(Object id, Object value) {
                  
          if (id == ID_X) {
                      getNode().setX(Integer.parseInt(value.toString()));
                  }
           else if (id == ID_Y) {
                      getNode().setY(Integer.parseInt(value.toString()));
                  }
           else if (id == ID_NAME) {
                      getNode().setName(value.toString());
                  }
           else if(id == ID_VISIBLE) {
                      getNode().setVisible(Boolean.getBoolean(value.toString()));
                  }

              }

              
          }


          在這個模型對應的EditPart中安裝這個PropertySource
          public Object getAdapter(Class key) {
                  
          if (IPropertySource.class == key)
                      
          return new NodePropertySource(getModel());
                  
          return super.getAdapter(key);
              }


          由于用
          EMF定義的model本身就實現了notifier,故在本例中采用了EMF的事件監聽機制。(采用GEF的事件監聽機制也是可行的)
          public void notifyChanged(Notification notification) {
                  
          int type = notification.getEventType();
                  
          int featureId = notification.getFeatureID(ModelPackage.class);
                  
          switch(type) {
                  
          case Notification.SET:
                      
          switch(featureId) {
                      
          case ModelPackage.NODE__X:
                      
          case ModelPackage.NODE__Y:
                      
          case ModelPackage.NODE__NAME:
                      
          case ModelPackage.NODE__VISIBLE:
                          refreshVisuals();
                          
          break;
                      }

                  
          case Notification.ADD:
                  
          case Notification.REMOVE:
                      
          switch(featureId) {
                      
          case ModelPackage.NODE__INPUTS:
                          refreshSourceConnections();
                          
          break;
                      
          case ModelPackage.NODE__OUTPUTS:
                          refreshTargetConnections();
                          
          break;
                      }

                  }

              }


          編輯器

           

          編輯器的其他重要組成部分,如Commandpolicy根原來的基本上沒區別,這里就不再敘述了。

           

          其他

           

          本例中不能從左邊的Explorer視圖中打開這個編輯器,而是用了Open ActionNew Action。原因是本插件項目打包后可以加載到Rcp項目中。

           

          本例的運行結果
          4.JPG

          除了上圖中的問題外,還有一些小bug,呵呵,我比較懶,基本不用它,所以就沒有改(Eclipse的懶加載法則)。這是我的一個面試考題,做這個例子,共用了1.5天。

           

           

          源碼

           

          點擊下載

           

          環境

           

          JDK1.4

          Eclipse 3.1

          GEF

          EMF

          posted on 2005-11-27 12:43 hopeshared 閱讀(2412) 評論(7)  編輯  收藏 所屬分類: EMF&GEF

          Feedback

          # re: emf&gef之一example.my.gefpractice 2005-11-29 17:20 wangzhiwei
          你是北航軟院哪一級的?  回復  更多評論
            

          # re: emf&gef之一example.my.gefpractice 2005-12-31 22:55 pandawang
          http://www.eclipseworld.org/bbs/read.php?tid=785&fpage=1
          剛剛看倒這個  回復  更多評論
            

          # re: emf&gef之一example.my.gefpractice 2006-01-02 12:21 hopeshared
          那個也是我發的  回復  更多評論
            

          # re: emf&gef之一example.my.gefpractice 2007-01-05 16:25 alf
          are you ?  回復  更多評論
            

          # re: emf&gef之一example.my.gefpractice 2007-01-05 16:29 alf
          hehe!
          時隔一年啊.....
          才看到......
          感謝
          你在那個公司啊?
          Boss 給你開多少啊....
          只是問問//看看是否有前途啊...Eclipse
            回復  更多評論
            

          # re: emf&gef之一example.my.gefpractice 2007-05-15 09:56 jack.yuan
          由于有這個問題,在定義Node的時候就一定要注意sourceConnections和targetConnections的這個屬性,一個是true,另一個是false。

          我沒有想明白,請明示,謝謝!  回復  更多評論
            

          # re: emf&gef之一example.my.gefpractice 2013-06-19 17:39 瘋狂De年糕
          @jack.yuan
          雖然已經過去N年了,但是還是希望能給后來可能看到的人以回答。也許不理解之前看到博主的這句話的確會有些困惑
          containment這個屬性表示了兩個EClass的強關聯關系
          sourceConnections和targetConnections如果將這個屬性同時設置為true,那么很遺憾,由于emf的驗證機制,一個Connection對象只能存在在這兩個集合之一
          如果同時設置為false,那么在寫入xml作持久化時會報錯,因為connection對象無法被識別為任何一個對象的子節點被保存
          解決方法之一即一個設為true,一個設為false。另一種方式參考八進制的方式,兩個都設置為false,但是需要多一個connections集合,diagram除與nodes結合關聯外還與這個connections集合關聯,當然這里的containment屬性為true  回復  更多評論
            

          主站蜘蛛池模板: 虹口区| 涡阳县| 浠水县| 普定县| 腾冲县| 峨山| 扎兰屯市| 朔州市| 周口市| 洞头县| 顺平县| 潼关县| 宜春市| 安西县| 喜德县| 南阳市| 尼勒克县| 乐山市| 怀柔区| 大关县| 康保县| 大足县| 双柏县| 连城县| 道孚县| 扶风县| 大宁县| 政和县| 扶沟县| 湖南省| 巧家县| 连南| 论坛| 临西县| 屏边| 恩施市| 濮阳县| 金山区| 东乡| 富平县| 界首市|