EMF是eclipse下面的一个相当优秀的自动生成代码的框架.IBM很多大型软件都是基于EMF做出来的,这足已说明它的成熟和优秀.
特别地,如果是要做eclipse插件,EMF带来的帮助更大,除了根据模型生成model代码外,它还能够生成和eclipes UI相关的viewer和相应的viewprovider(控制层).
EMF其实不难,网上有很多关于EMF入门的文章,我这里也就不多废话了.
今天的主题是把前面的例子用EMF+GEF实现.

回顾一下前面的model,他们的UML图如下:
GEF学习教程5-Unplugged版(结合EMF和GEF)

EMF需要我们先定义好model,然后它会根据model自动生成代码.可以有好几种方法,UML图(Rose),Java Codes, XML文件.我自己偏向于用Java代码来定义,因为自己没钱买rose,而XML我很容易出错(就没成功过).

根据上面的UML图,每个类的Java代码如下
Content.java
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)/***//**
GEF学习教程5-Unplugged版(结合EMF和GEF)*@model
GEF学习教程5-Unplugged版(结合EMF和GEF)
*/

GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
publicinterfaceContent...{
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
/***//**
GEF学习教程5-Unplugged版(结合EMF和GEF)*@modelcontainment="true"type="Page"
GEF学习教程5-Unplugged版(结合EMF和GEF)
*/

GEF学习教程5-Unplugged版(结合EMF和GEF)
publicListgetChildren();
GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)
publicvoidaddChild(Pagechild);
GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)
publicvoidremoveChild(Pagechild);
GEF学习教程5-Unplugged版(结合EMF和GEF)}

Page.java
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)/***//**
GEF学习教程5-Unplugged版(结合EMF和GEF)*@model
GEF学习教程5-Unplugged版(结合EMF和GEF)
*/

GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
publicinterfacePage...{
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
/***//**
GEF学习教程5-Unplugged版(结合EMF和GEF)*@modelcontainment="true"type="Control"
GEF学习教程5-Unplugged版(结合EMF和GEF)
*/

GEF学习教程5-Unplugged版(结合EMF和GEF)
publicListgetChildren();
GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
/***//**
GEF学习教程5-Unplugged版(结合EMF和GEF)*@model
GEF学习教程5-Unplugged版(结合EMF和GEF)
*/

GEF学习教程5-Unplugged版(结合EMF和GEF)
publicRectanglegetConstraint();
GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)
publicvoidaddChild(Controlchild);
GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)
publicvoidremoveChild(Controlchild);
GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)}

Control.java
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)/***//**
GEF学习教程5-Unplugged版(结合EMF和GEF)*@model
GEF学习教程5-Unplugged版(结合EMF和GEF)
*/

GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
publicinterfaceControl...{
GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)}

Container.java
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)/***//**
GEF学习教程5-Unplugged版(结合EMF和GEF)*@model
GEF学习教程5-Unplugged版(结合EMF和GEF)
*/

GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
publicinterfaceContainerextendsControl...{
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
/***//**
GEF学习教程5-Unplugged版(结合EMF和GEF)*@modelcontainment="true"type="Column"
GEF学习教程5-Unplugged版(结合EMF和GEF)
*/

GEF学习教程5-Unplugged版(结合EMF和GEF)
publicListgetChildren();
GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)
publicvoidaddChild(Columnchild);
GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)
publicvoidremoveChild(Columnchild);
GEF学习教程5-Unplugged版(结合EMF和GEF)}

Column.java
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)/***//**
GEF学习教程5-Unplugged版(结合EMF和GEF)*@model
GEF学习教程5-Unplugged版(结合EMF和GEF)
*/

GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
publicinterfaceColumn...{
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
/***//**
GEF学习教程5-Unplugged版(结合EMF和GEF)*@modelcontainment="true"type="Node"
GEF学习教程5-Unplugged版(结合EMF和GEF)
*/

GEF学习教程5-Unplugged版(结合EMF和GEF)
publicListgetChildren();
GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
/***//**
GEF学习教程5-Unplugged版(结合EMF和GEF)*@modeldefault="column"
GEF学习教程5-Unplugged版(结合EMF和GEF)
*/

GEF学习教程5-Unplugged版(结合EMF和GEF)
publicStringgetName();
GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)
publicvoidaddChild(Nodenode,intindex);
GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)
publicvoidaddChild(Nodenode);
GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)
publicvoidremoveChild(Nodenode);
GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)}

Node.java
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)/***//**
GEF学习教程5-Unplugged版(结合EMF和GEF)*@model
GEF学习教程5-Unplugged版(结合EMF和GEF)
*/

GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
publicinterfaceNode...{
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
/***//**
GEF学习教程5-Unplugged版(结合EMF和GEF)*@modeldefault="node"
GEF学习教程5-Unplugged版(结合EMF和GEF)
*/

GEF学习教程5-Unplugged版(结合EMF和GEF)
publicStringgetName();
GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)}

Label.java
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)/***//**
GEF学习教程5-Unplugged版(结合EMF和GEF)*@model
GEF学习教程5-Unplugged版(结合EMF和GEF)
*/

GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
publicinterfaceLabelextendsControl...{
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
/***//**
GEF学习教程5-Unplugged版(结合EMF和GEF)*@modeldefault="label"
GEF学习教程5-Unplugged版(结合EMF和GEF)
*/

GEF学习教程5-Unplugged版(结合EMF和GEF)
publicStringgetName();
GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)}

MyButton.java
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)/***//**
GEF学习教程5-Unplugged版(结合EMF和GEF)*@model
GEF学习教程5-Unplugged版(结合EMF和GEF)
*/

GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
publicinterfaceMyButtonextendsControl...{
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
/***//**
GEF学习教程5-Unplugged版(结合EMF和GEF)*@modeldefault="button"
GEF学习教程5-Unplugged版(结合EMF和GEF)
*/

GEF学习教程5-Unplugged版(结合EMF和GEF)
publicStringgetName();
GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)}

选择model文件夹,右键新建EMF Model,选择从Java代码得到model,文件名写geftest.genmodel,完成.然后就会自动生成geftest.ecore和geftest.genmodel两个文件,ecore文件保存的是emf core需要的信息, 而genmodel是一些比如生成的包名等和core无关的其它信息.

右键点ecore文件,然后选择:Initialize ecore_diagram diagram file,生成diagram_file文件,打开后得到下图:
GEF学习教程5-Unplugged版(结合EMF和GEF)

可以看出来我们的model定义的是正确的.
然后修改一些地方就可以了.

EMF生成的代码有一个完整的事件机制,每个对象都可以有许多adapter,对象属性被改后会通知这些adapter.
所以我把以前的AbstractModel删掉了.然后把每个editpart做为它的model的adapter就可以了.这需要我们的所有editpart都实现Adapter接口.

因为我们的editpart都继承AbstractEditPartWithListener,所以我把里面原来的加入到listener list的代码都删掉了,加了如下代码:
EditPartWithListener.java
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)protectedvoidhookIntoModel(EObjectmodel)...{
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
if(model!=null)...{
GEF学习教程5-Unplugged版(结合EMF和GEF)model.eAdapters().add(
this);
GEF学习教程5-Unplugged版(结合EMF和GEF)}

GEF学习教程5-Unplugged版(结合EMF和GEF)}

GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
protectedvoidunhookFromModel(EObjectmodel)...{
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
if(model!=null)...{
GEF学习教程5-Unplugged版(结合EMF和GEF)model.eAdapters().remove(
this);
GEF学习教程5-Unplugged版(结合EMF和GEF)}

GEF学习教程5-Unplugged版(结合EMF和GEF)}

GEF学习教程5-Unplugged版(结合EMF和GEF)@Override
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
publicvoidactivate()...{
GEF学习教程5-Unplugged版(结合EMF和GEF)hookIntoModel((EObject)getModel());
GEF学习教程5-Unplugged版(结合EMF和GEF)
super.activate();
GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)}

GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)@Override
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
publicvoiddeactivate()...{
GEF学习教程5-Unplugged版(结合EMF和GEF)unhookFromModel((EObject)getModel());
GEF学习教程5-Unplugged版(结合EMF和GEF)
super.deactivate();
GEF学习教程5-Unplugged版(结合EMF和GEF)}
然后每个EditPart实现notifyChanged方法:
举个例子,比如PageEditPart:
PageEditPart.java
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)publicvoidnotifyChanged(Notificationnotification)...{
GEF学习教程5-Unplugged版(结合EMF和GEF)
inttype=notification.getEventType();
GEF学习教程5-Unplugged版(结合EMF和GEF)
intfeatureId=notification.getFeatureID(ModelPackage.class);
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
switch(type)...{
GEF学习教程5-Unplugged版(结合EMF和GEF)
caseNotification.ADD:
GEF学习教程5-Unplugged版(结合EMF和GEF)
caseNotification.REMOVE:
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
switch(featureId)...{
GEF学习教程5-Unplugged版(结合EMF和GEF)
caseModelPackage.PAGE__CHILDREN:
GEF学习教程5-Unplugged版(结合EMF和GEF)refreshChildren();
GEF学习教程5-Unplugged版(结合EMF和GEF)
break;
GEF学习教程5-Unplugged版(结合EMF和GEF)}

GEF学习教程5-Unplugged版(结合EMF和GEF)
caseNotification.SET:
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
switch(featureId)...{
GEF学习教程5-Unplugged版(结合EMF和GEF)
caseModelPackage.PAGE__CONSTRAINT:
GEF学习教程5-Unplugged版(结合EMF和GEF)refreshVisuals();
GEF学习教程5-Unplugged版(结合EMF和GEF)
break;
GEF学习教程5-Unplugged版(结合EMF和GEF)}

GEF学习教程5-Unplugged版(结合EMF和GEF)}

GEF学习教程5-Unplugged版(结合EMF和GEF)}

最后修改Editor的ToolEntry.因为我们不能用SimpleFactory来简单的用反射生成每个model对象.
而应该用ModelFactory.eINSTANCE.createXXX方法.
Editor.java
GEF学习教程5-Unplugged版(结合EMF和GEF)CreationToolEntrycreationPage=newCreationToolEntry("drawpage",
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
"createpage",newCreationFactory()...{
GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
publicObjectgetNewObject()...{
GEF学习教程5-Unplugged版(结合EMF和GEF)
returnModelFactory.eINSTANCE.createPage();
GEF学习教程5-Unplugged版(结合EMF和GEF)}

GEF学习教程5-Unplugged版(结合EMF和GEF)
GEF学习教程5-Unplugged版(结合EMF和GEF)GEF学习教程5-Unplugged版(结合EMF和GEF)
publicObjectgetObjectType()...{
GEF学习教程5-Unplugged版(结合EMF和GEF)
returnnull;
GEF学习教程5-Unplugged版(结合EMF和GEF)}

GEF学习教程5-Unplugged版(结合EMF和GEF)}
,descriptor,descriptor);
GEF学习教程5-Unplugged版(结合EMF和GEF)drawer.add(creationPage);

基本上这样就OK了,其实不麻烦.

代码下载

参考资源:
EMF
Using GEF with EMF
GEF学习教程-Unplugged版

相关文章: