精彩的人生

          好好工作,好好生活

          BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
            147 Posts :: 0 Stories :: 250 Comments :: 0 Trackbacks
          本文是原創(chuàng)作品,如有轉(zhuǎn)載,請(qǐng)注明出處!

           

          GEF編輯器的人,不知道有沒(méi)有發(fā)現(xiàn)這樣一個(gè)問(wèn)題:每當(dāng)作一個(gè)新的編輯器的時(shí)候,有很多代碼都和以前的類似。

          我發(fā)現(xiàn)了這個(gè)問(wèn)題,很多CommandPolicy,包括EditPart都很類似,所以我經(jīng)常采用Copy&Paste然后修改的方法來(lái)加快開(kāi)發(fā)速度。

          Eclipse采用的是插件擴(kuò)展機(jī)制,做一次擴(kuò)展就可以向Eclipse貢獻(xiàn)一個(gè)新的功能。同理,GEF編輯器中,畫(huà)板里的可編輯模型,是否也能這樣添加呢?

          讓我們沿著這個(gè)思路走下去。

           

          定義模型

          初步的構(gòu)想,仍然是繼續(xù)前兩篇文章的足跡,更改原來(lái)的例子。

           

          模型的定義:
          emfgef3_1.JPG

           

          最開(kāi)始做這個(gè)例子的時(shí)候,我將NodeAbstract設(shè)置為了true,因?yàn)槲蚁M褪且粋€(gè)抽象類,我將寫(xiě)RectangleNodeEllipseNode繼承Node,他們才會(huì)出現(xiàn)在編輯器里。但是后來(lái)發(fā)現(xiàn)那樣做的話,文件確實(shí)可以編輯,但是文件保存之后,再次用EMF序列化為對(duì)象的時(shí)候會(huì)出錯(cuò)。

          什么?不信?那你自己試試。

          這里,我給Node加了一個(gè)屬性instance,它表示這個(gè)對(duì)象的實(shí)現(xiàn)類。它將給我們代來(lái)一些麻煩。

           

          創(chuàng)建模型工程

           

          與前面的文章一樣,利用這個(gè)ecore文件創(chuàng)建一個(gè)EMF項(xiàng)目,并生成模型代碼。Ok,就把代碼放在這里,不再改動(dòng)它了。這個(gè)工程的名稱是nodenew

           

          創(chuàng)建編輯器工程

           

          如果說(shuō)前面的工程僅創(chuàng)建了“抽象模型”,那么本工程就僅創(chuàng)建了基于前面模型的一個(gè)編輯器框架

          創(chuàng)建一個(gè)名為nodenew.gef的插件項(xiàng)目,其他的全部按默認(rèn)設(shè)置。首先,這個(gè)插件依賴于nodenew。將nodetest中的commandeditpartconnectionhelppropertiesuicopy過(guò)來(lái),將Connection.javaModelManager.javacopy過(guò)來(lái),修改代碼,盡可能的減少那些紅叉。

          創(chuàng)建一個(gè)擴(kuò)展點(diǎn),我們將利用它來(lái)初始化編輯器畫(huà)板。

          emfgef3_2.JPG


           

          這個(gè)擴(kuò)展點(diǎn)的用意很明確,就是貢獻(xiàn)模型并設(shè)置模型與EditPart的對(duì)應(yīng)關(guān)系。

           

          創(chuàng)建一個(gè)接口類,所有使用這個(gè)擴(kuò)展點(diǎn)的EditPart需要實(shí)現(xiàn)這個(gè)接口:

          MyEditPart.java

          public interface MyEditPart extends NodeEditPart{
              
          public void setConnection(Object model);
              
          public void removeConnection(Object model);
          }

           

          創(chuàng)建一個(gè)類,從擴(kuò)展點(diǎn)中找到模型與EditPart的對(duì)應(yīng)關(guān)系:

           

          ModelToEditPartMap.java

          public class ModelToEditPartMap {
              
              
          private static Hashtable map = getTable();
              
              
          public static Hashtable getTable(){
                  
          if(map==null){  
                      map
          =new Hashtable();
                      IExtensionRegistry registry 
          = Platform.getExtensionRegistry();
                      IExtensionPoint point 
          = registry.getExtensionPoint(MyConstants.FACTORY_EXTIONPOINT_ID);
                      
          if (null == point){
                          System.err.println(
          "No extension point called "+MyConstants.FACTORY_EXTIONPOINT_ID+" is found!");
                          
          return null;
                      }

                      IExtension[] extensions 
          = point.getExtensions();
                      
          for (int i = 0; i < extensions.length; i++){
                          IConfigurationElement[] elements 
          = extensions[i].getConfigurationElements();
                          
          for (int j = 0; j < elements.length; j++){
                              
          if (elements[j].getAttribute(MyConstants.ATTR_TARGETEDITORID).equals(MyConstants.EDITOR_ID)){
                                  String eleType 
          = elements[j].getName();
                                  
          if (eleType.equals(MyConstants.ELEMENT_NODEPART)){
                                      
          try{
                                          map.put(elements[j].getAttribute(MyConstants.ATTR_MODELCLASS), elements[j]);
                                          System.out.println(
          "add a node " + elements[j].getAttribute(MyConstants.ATTR_NAME) + "to map");
                                      }

                                      
          catch(Exception e){
                                          e.printStackTrace();
                                      }

                                  }

                              }

                          }

                      }

                  }

                  
          return map;
              }


          }

           

          創(chuàng)建一個(gè)類,從擴(kuò)展點(diǎn)中得到編輯器畫(huà)板里的元素。

           

          FactoryExtension.java

          public class FactoryExtension {    
              
          private static ArrayList factory = getFactory();
              
              
          public static ArrayList getFactory() {
                  
          if(factory==null){  
                      factory
          =new ArrayList();
                      IExtensionRegistry registry 
          = Platform.getExtensionRegistry();
                      IExtensionPoint point 
          = registry.getExtensionPoint(MyConstants.FACTORY_EXTIONPOINT_ID);
                      
          if (null == point){
                          System.err.println(
          "No extension point called "+MyConstants.FACTORY_EXTIONPOINT_ID+" is found!");
                          
          return null;
                      }

                      IExtension[] extensions 
          = point.getExtensions();
                      
          for (int i = 0; i < extensions.length; i++){
                          IConfigurationElement[] elements 
          = extensions[i].getConfigurationElements();
                          String pluginId 
          = extensions[i].getNamespace();
                          Plugin a 
          = null;
                          
          try {
                              a 
          = extensions[i].getDeclaringPluginDescriptor().getPlugin();
                          }
           catch (InvalidRegistryObjectException e1) {
                              
          // TODO Auto-generated catch block
                              e1.printStackTrace();
                          }
           catch (CoreException e1) {
                              
          // TODO Auto-generated catch block
                              e1.printStackTrace();
                          }

                          a.getBundle();
                          
                          
                          
                          
          for (int j = 0; j < elements.length; j++){
                              
          if (elements[j].getAttribute(MyConstants.ATTR_TARGETEDITORID).equals(MyConstants.EDITOR_ID)){
                                  String eleType 
          = elements[j].getName();
                                  
          if (eleType.equals(MyConstants.ELEMENT_NODEPART)){
                                      
          if(!Boolean.parseBoolean(elements[j].getAttribute(MyConstants.ATTR_VISIBLE))){
                                          
          continue;
                                      }

                                      
          try{
                                          ImageDescriptor descriptor 
          = null;
                                          
          try{
                                              
          if(elements[j].getAttribute(MyConstants.ATTR_ICON)!=null)
                                                  descriptor 
          = AbstractUIPlugin.imageDescriptorFromPlugin(pluginId, elements[j].getAttribute(MyConstants.ATTR_ICON));
                                          }
           catch(Exception e){
                                              e.printStackTrace();
                                          }

                                          
          if(descriptor == null){
                                              descriptor 
          = GefPlugin.getImageDescriptor(MyConstants.IMG_DEFAULT);
                                          }

                                          
                                          ToolEntry tool 
          = new CombinedTemplateCreationEntry(
                                                  elements[j].getAttribute(MyConstants.ATTR_NAME), 
                                                  
          "Create a new Node"
                                                  elements[j].getAttribute(MyConstants.ATTR_MODELCLASS), 
                                                  
          new MyCreationFactory(elements[j]), descriptor,descriptor);

                                          factory.add(tool);
                                          System.out.println(
          "add a node " + elements[j].getAttribute(MyConstants.ATTR_NAME));
                                      }

                                      
          catch(Exception e){
                                          e.printStackTrace();
                                      }

                                  }

                              }

                          }

                      }

                  }

                  
          return factory;
              }

              
              
          }

           

          上面的類中使用的CreationFactory是自己重寫(xiě)的一個(gè)類,它的目的在于,當(dāng)用戶選中畫(huà)板中的一個(gè)對(duì)象的時(shí)候,發(fā)出了一個(gè)createrequest,我們創(chuàng)建一個(gè)對(duì)象,封裝在這個(gè)request里,當(dāng)編輯器截獲這個(gè)request的時(shí)候,就直接得到了新創(chuàng)建的這個(gè)模型對(duì)象。

           

          MyCreationFactory.java

          public class MyCreationFactory implements CreationFactory{
              
              
          private IConfigurationElement element;
              
              
          public MyCreationFactory(IConfigurationElement element){
                  
          this.element = element;
              }

              
              
          public Object getNewObject() 
                          
                  
          try {
                      Object classname
          =null
                      
                      
          try {
                          classname 
          = WorkbenchPlugin.createExtension(element, MyConstants.ATTR_MODELCLASS);
                      }
           catch (CoreException e) {
                          
          // TODO Auto-generated catch block
                          e.printStackTrace();
                      }

                      
                      
          if(classname instanceof Class)
                          System.out.println(
          "class");
                      
                      
          return classname;
          //            
                  }
           catch (InvalidRegistryObjectException e) {
                      
          // TODO Auto-generated catch block
                      e.printStackTrace();
                  }
           
                  
          return null;
              }

              
          public Object getObjectType() {        
                  
          return element.getAttribute(MyConstants.ATTR_MODELCLASS); 
              }


          }

           

          在這里碰到了一個(gè)關(guān)于ClassLoader的問(wèn)題。假如不使用WorkbenchPlugin.createExtension(element, MyConstants.ATTR_MODELCLASS);

          從當(dāng)前的插件項(xiàng)目中load這個(gè)class會(huì)出現(xiàn)ClassNotFound異常。目前的這個(gè)解決方法不是很好,正在尋找更好的解決方案。

           

          接著,修改NodeEditorPaletteFactory,從擴(kuò)展點(diǎn)中初始化編輯器畫(huà)板:

          private static PaletteContainer createShapesDrawer() {
              PaletteDrawer componentsDrawer 
          = new PaletteDrawer("Shapes");
              CombinedTemplateCreationEntry component
          =null;
              ArrayList factory 
          = FactoryExtension.getFactory();
              
          if(factory!=null && factory.size()>1){
                  
          for(int i=0; i<factory.size(); i++){
                      component 
          = (CombinedTemplateCreationEntry) factory.get(i);
                      componentsDrawer.add(component);
                  }

              }

              
          return componentsDrawer;
          }

           

          最后,修改NodesEditPartFactory,有些對(duì)象需要從擴(kuò)展點(diǎn)中得到EditPart對(duì)象:

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

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

                  
                  EditPart result 
          = null;
                  
          if(modelElement instanceof Node){
                      
                      String classname 
          = ((Node)modelElement).getInstance();
                      IConfigurationElement element 
          = (IConfigurationElement)ModelToEditPartMap.getTable().get(classname);
                      
          try {                
                          result 
          = (EditPart) WorkbenchPlugin.createExtension(element, MyConstants.ATTR_PARTCLASS);
                      }
           catch (CoreException e) {
                          
          // TODO Auto-generated catch block
                          e.printStackTrace();
                      }

                      
                  }

                  
                  
          if(result==null){
                  
                      
          if(ModelToEditPartMap.getTable().containsKey(modelElement.getClass().getName())){
                          
          try {
                              IConfigurationElement element 
          = (IConfigurationElement)ModelToEditPartMap.getTable().get(modelElement.getClass().getName());
                          
                              result 
          = (EditPart) WorkbenchPlugin.createExtension(element, MyConstants.ATTR_PARTCLASS);

                          }
          catch (CoreException e) {
                              
          // TODO Auto-generated catch block
                              e.printStackTrace();
                          }

                      }

                  }

                  
                  
          if(result!=null && result instanceof MyEditPart){
                      ((MyEditPart)result).removeConnection(modelElement);
                      ((MyEditPart)result).setConnection(modelElement);            
                      
          return result;
                  }

                  
                  
          throw new RuntimeException(
                          
          "Can't create part for model element: "
                          
          + ((modelElement != null? modelElement.getClass().getName() : "null"));
              }

           

          這個(gè)時(shí)候,編輯器的框架已經(jīng)搭建好了,運(yùn)行一下看看吧。
          emfgef3_3.JPG

           

          可以看到,畫(huà)板里的Connection是一直都有的,但是卻沒(méi)有Node對(duì)象。

           

          創(chuàng)建自己的擴(kuò)展

           

          再建一個(gè)新的插件項(xiàng)目,名為nodenew.my,它依賴于前面的2個(gè)插件。

           

          首先創(chuàng)建模型對(duì)象:

           

          EllipseNode.java

          public class EllipseNode extends NodeImpl{
              
          public EllipseNode(){
                  
          super();
                  
          this.instance = this.getClass().getName();
              }

          }


          RectangleNode.java

          public class RectangleNode extends NodeImpl{
              
          public RectangleNode(){
                  
          super();
                  
          this.instance = this.getClass().getName();
              }

          }

           

          接著創(chuàng)建EditPart

           

          EllipseNodeEditPart.java

          public class EllipseNodeEditPart extends NodesEditPart implements MyEditPart{
              
          protected IFigure createFigure() {
                  IFigure f 
          = new Ellipse();
                  
                  f.setOpaque(
          true); // non-transparent figure
                  f.setBackgroundColor(ColorConstants.green);
                  
          return f;
              }

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

                      }

                  }

              }
              
              
              
          public void setConnection(Object model){
                  
          if(((Node)model).getNext()!=null && ((Node)model).getNext().size()>0){
                      
          for(int i=0; i<((Node)model).getNext().size(); i++){
                          Connection c 
          = new Connection();
                          c.setSource((Node) model);
                          c.setTarget((Node) ((Node)model).getNext().get(i));
                          
          this.getModelTargetConnections().add(c);
                          TargetAddConnectionTable.getInstance().add(c, (Node) c.getTarget());
                      }

                  }

              }


          }

           

          RectangleNodeEditPart.java

          public class RectangleNodeEditPart extends NodesEditPart implements MyEditPart{
              
          protected IFigure createFigure() {
                  IFigure f 
          = new RectangleFigure();
                  f.setOpaque(
          true); // non-transparent figure
                  f.setBackgroundColor(ColorConstants.green);
                  
          return f;
              }

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

                      }

                  }

              }
              
              
              
              
          public void setConnection(Object model){
                  
          if(((Node)model).getNext()!=null && ((Node)model).getNext().size()>0){
                      
          for(int i=0; i<((Node)model).getNext().size(); i++){
                          Connection c 
          = new Connection();
                          c.setSource((Node) model);
                          c.setTarget((Node) ((Node)model).getNext().get(i));
                          
          this.getModelTargetConnections().add(c);
                          TargetAddConnectionTable.getInstance().add(c, (Node) c.getTarget());
                      }

                  }

              }


          }

           

          聲明本次擴(kuò)展:

           

          plugin.xml

          <extension
                   
          point="nodenew.gef.editpartfactory">
                
          <nodepart
                      
          modelclass="nodenew.model.EllipseNode"
                      name
          ="nodenew.my.nodepart1"
                      partclass
          ="nodenew.editpart.EllipseNodeEditPart"
                      targetEditorId
          ="nodenew.ui.NodesEditor"
                      visible
          ="true"/>
                
          <nodepart
                      
          modelclass="nodenew.model.RectangleNode"
                      name
          ="nodenew.my.nodepart1"
                      partclass
          ="nodenew.editpart.RectangleNodeEditPart"
                      targetEditorId
          ="nodenew.ui.NodesEditor"
                      visible
          ="true"/>
             
          </extension>

           

          看看結(jié)果吧
          emfgef3_4.JPG

           

          其他

           

          本例仍然利用兩個(gè)action來(lái)打開(kāi)編輯器。

           

          不知道這次的研究成果是不是可以發(fā)表成學(xué)術(shù)論文呢??我覺(jué)得挺有創(chuàng)意的,呵呵。

           

          源碼

           

          點(diǎn)擊下載

           

          運(yùn)行環(huán)境

           

          JDK 1.4

          Eclipse 3.1

          EMF

          GEF

          posted on 2005-12-15 15:57 hopeshared 閱讀(3095) 評(píng)論(1)  編輯  收藏 所屬分類: EMF&GEF

          Feedback

          # re: emf&gef之三nodenew 2005-12-15 18:00 marmot
          - -!!  回復(fù)  更多評(píng)論
            

          主站蜘蛛池模板: 琼海市| 武安市| 雷波县| 大邑县| 金川县| 兴安县| 镇远县| 定安县| 吉首市| 崇明县| 阿城市| 南和县| 沅陵县| 鸡东县| 马公市| 惠来县| 上栗县| 柯坪县| 潍坊市| 长治市| 吉首市| 阿拉善左旗| 唐河县| 类乌齐县| 北流市| 中西区| 蓬莱市| 綦江县| 平凉市| SHOW| 灯塔市| 兰溪市| 荥阳市| 舟曲县| 武山县| 乌苏市| 天等县| 巴彦县| 武威市| 宜昌市| 抚远县|