- 浏览: 2469591 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (574)
- Book (62)
- Architecture (6)
- Java (39)
- Taobao (41)
- Distributed (4)
- Life (72)
- Database (7)
- Spring (16)
- Photography (15)
- Bicycle (41)
- Test (20)
- jBPM (8)
- Business (12)
- Movie (3)
- Ajax (15)
- Code (7)
- Eclipse (96)
- VIM (2)
- Music (6)
- Groovy (10)
- AutoHotKey (3)
- Dorado (10)
- Maven (7)
- Scrum (5)
- English (20)
- Financial (12)
- OSGi (3)
- Other (4)
- Tool (6)
- Browser (1)
- PPT (1)
- Project Management (4)
- Agile (6)
- Nosql (1)
- Search engine (6)
- Shell (2)
- Open Source (4)
- Storm (10)
- Guava (3)
- Baby (1)
- netty (1)
- Algorithm (1)
- Linux (1)
- Python (2)
最新评论
-
roy2011a:
https://github.com/ebottabi/sto ...
storm的序列化问题及与spring的结合方式 -
roy2011a:
能抗能打 写道哥们儿,你好!能共享下那个storm与sprin ...
storm的序列化问题及与spring的结合方式 -
Alick1:
兄弟,你之前是不是在深圳的正阳公司呆过啊?
storm的ack和fail -
liuleixwd:
先点个赞,写的非常好!有个问题请教下,如果我再bolt里不用e ...
storm的ack和fail -
yao-dd:
solr的facet查询
FROM:http://www.rcp.org.cn/bbs_topic.do?forumID=7&postID=164
原文:http://www.eclipse.org/articles/Article-GEF-editor/gef-schema-editor.html
用过Eclipse相关产品的人经常会看到一些涉及到图形应用的插件,比如Struts、UML、DatabaseDesign相关的插件;或者企业中自己要定制自己的图形化的工作流编辑器,组织结构图等。这些都涉及到图形编辑,以前我们大多用Win32 API或JFC/Java2D技术自己做框架来实现这些功能,复杂且工作量大!
GEF(Graphical Editor Framework)是现在Eclipse领域流行的图形编辑框架,它可以用来给用户提供图形化编辑模型的功能,从而提升用户体验。它同时具有Windows的美观界面和JFC的跨平台能力,并可以与draw2D(Eclispe领域想要取代java2D的图形API)达到良好的结合。
GEF里用到了很多经典的结构模式和设计模式,如MVC,Policy,Command,Observer等,方便的实现Undo/Redo功能等等,通过学习GEF,也可以更好地掌握这些模式.
在本文中,我们将介绍GEF/draw2D,并简介用GEF如何一步步的做一个数据库模型编辑器。
读者朋友们可能已经看到了前面文章所介绍的Eclipse体系结构了,这里还有一张图对GEF与Eclispe平台之间的关系作了描述:SWT和Draw2D的关系就相当于AWT与Java2D的关系,而GEF这个框架是基于ui.views和RCP(见本系列另一篇关于RCP的文章)概念之上的。
说到GEF框架,还是要从我们熟悉的MVC模式说起,MVC是一种通用的涉及到UI交互的模式,通常Model代表数据的显示,View则负责在界面上呈现数据,而Controller的职责是处理用户的输入以及根据Model的修改刷新View。一般情况下,一个UI(View)只被用于呈现一个Model,但是在GEF里面任何View可以被用于呈现任意的Model,也就是说在GEF里View-to-Model的映射并不是1-to-1的,在GEF中MVC的定义如下:
Model:任何GEF 应用的起点就是Model。它们需要被显示, 编辑和持久化。Model应该对View和Controller的细节一无所知,它仅仅可以把自己的改变负责通知给View和Controller,在GEF中,Model只能被Commands所更新。
View:View包括Draw2D中一种虚拟组件Figure来呈现Model对象, GEF也支持SWT中的TreeItem对象。另外,与View相关的还包括feedback,handle,tooltip等等。所有这些View组件都由Controller来构建和管理它们。
Controller:就是EditPart,EditPart在GEF里面是最关键的组件,负责管理整个View层面的所有组件。后面会有详细 介绍
在我们的这个数据库模型编辑器中,我们定义了我们的MVC架构:
我们的Model:
我们的Model分成如下几种:
• Table: 代表一张关系数据库表。 唯一的属性是表名
• Column: 数据库表的列。 我们比较感兴趣的属性是列名和数据类型( 可能是VARCHAR 或整型)。
• Relationship: 表现为两张数据库表之间的主外键关系。
• Schema: 简单地可以代表所有表的分组。
我们的模型很简单, 但至少包括在一个典型的GEF 模型中两种关键的对象关系:
• 在table和schema之间以及table和column之间存在父子关系
• 在不同的节点(Node)之间的连接关系。 在我们的例子中, connection是以主外键 关系的形式
我们的View
在View这一部分的介绍,我们分别介绍Figure和布局管理器这两部分:
Figure
Figure在draw2d 中是一种创建复杂图形的轻量级对象。视图则是由一组反映model的Figures来组建的。 在典型的GEF 应用中, 您通常会创建一组定制的Figure类并实现IFigure 接口。
在我们的应用中有以下的Figure:
EditableLabel: draw2d中Label的子类。 用于为column和table命名。
ColumnsFigure: 所有column的一个容器。
TableFigure: 包含EditableLabel 和ColumnsFigure
SchemaFigure: 在Schema中包含所有TableFigures
另外,我们并未提供任何特别的figure来代表图中的连接线, 我们简单地使用draw2d 的PolylineConnection 类, 来代表一条有0或多个拐点(bend point) 的连接线。
由于表名,列名,列数在一个TableFigure 实例的生命周期内可以增加或减少的, 我们也可以重设我们的ColumnsFigure 和TableFigure的尺寸。这个功能由布局管理器(draw2d 的另一个重要部份)担当。
布局管理器
GEF 提供与Swing和SWT 的LayoutManager不同的一个布局管理框架: 它的职责是处理实现draw2d IFigure的Figure的布局。应用开发者将决定用某个LayoutManager来布局每一个包含子Figure的Figure。
宽泛地讲, 有三类型LayoutManager:
• 结构化布局管理器,比如FlowLayout 和ToolbarLayout, 可以根据子figure的次序来垂直或水平地布局
• 基于约束的布局管理器,譬如XYLayout 和DelegatingLayout 。为每个子figure设置一个Constraint对象。 在XYLayout 情况下, 这个对象是一个Rectangle对象来指定位置和尺寸。
• 使用几何算法的布局管理器, 这种布局为子figure运用一系列的相当复杂算法来计算布局。这种 算法采取一种特殊的数据结构作为譬如Node的安置和path的路由之类几何问题的解决方案。GEF 由DirectedGraphLayout 和CompoundDirectedGraphLayout提供算法。
GEF 开发者需要理解特定的LayoutManager被应用于特定的情况。在我们的应用中ColumnsFigure 使用FlowLayout来布局它的Label组件。TableFigure 使用ToolbarLayout 来布局它的子组件(简单地垂直摆放) 。大家可以看一下TableFigure的初始化过程:
- public TableFigure(EditableLabel name, List colums)
- {
- nameLabel = name;
- ToolbarLayout layout = new ToolbarLayout();
- layout.setVertical(true);
- layout.setStretchMinorAxis(true);
- setLayoutManager(layout);
- setBorder(new LineBorder(ColorConstants.black, 1));
- setBackgroundColor(tableColor);
- setForegroundColor(ColorConstants.black);
- setOpaque(true);
- name.setForegroundColor(ColorConstants.black);
- add(name);
- add(columnsFigure);
- }
我们的Controller:
当我们开始谈论控制器才算真正走入GEF领域。 GEF 提供了EditPart来避免Model知道关于View Part(Figure)的细节, 并且反之亦然。
EditParts:
一般情况下,我们需要为每个Model创建一个EditPart实例(通常我们都是通过继承AbstractEditPart来创建我们自己的EditPart),所以我们必须使我们的EditParts的继承结构和Model的继承结构相匹配。每个EditPart (也就是GraphicalEditPart), 会处理一个Model组件, 并且关联一个视图组件。 由于模型和视图完全地被分离, 所有在模型和视图之间的协调必须由EditPart 处理。
在我们的模型编辑器的实现中,有如下的EditPart实现:
• SchemaDiagramPart: 表现为一个Schema实例及其相关的 SchemaFigure
• TablePart: 表现为一个Table并且管理这个Table相关的TableFigure及其子Figure
• ColumnPart: 能够让我们编辑 column label
• RelationshipPart: 表现为一个主外键关系. 一个 RelationshipPart关联两个 TableParts
我们可以用一个EditPartFactory来提供EditPart:
- public class SchemaEditPartFactory implements EditPartFactory
- {
- public EditPart createEditPart(EditPart context, Object model)
- {
- EditPart part = null;
- if (model instanceof Schema)
- part = new SchemaDiagramPart();
- else if (model instanceof Table)
- part = new TablePart();
- else if (model instanceof Relationship)
- part = new RelationshipPart();
- else if (model instanceof Column)
- part = new ColumnPart();
- part.setModel(model);
- return part;
- }
- }
在GEF应用中,有以下一些任务EditPart的子类必须实现:
1.提供一个EditPart相关的Figure实例
- protected IFigure createFigure()
- {
- Table table = getTable();
- EditableLabel label = new EditableLabel(table.getName());
- TableFigure tableFigure = new TableFigure(label);
- return tableFigure;
- }
- protected List getModelChildren()
- {
- return getTable().getColumns();
- }
3.如果代表父EditPart的Figure并非子EditPart的Figure的直接父类,那么需要实现AbstractGraphicalEditPart.getContentPane(),返回子EditPart的Figure
在我们的例子中可以从一个TableFigure的实例中得到ColumnPart的ColumnFugure
- public IFigure getContentPane()
- {
- TableFigure figure = (TableFigure) getFigure();
- return figure.getColumnsFigure();
- }
Request:
Request是处理GEF 应用中的一个编辑动作的起点。GEF 能用面向对象的方式处理用户交互和转发这些requests。例如, 当我们从“New Column”这个调色板(palette)按钮拖放一个column到图中的一个表中时,相当于用户与GEF应用的交互,GEF应用在后台将创建request对象。 比如创建column时, GEF 将产生CreateRequest对象。
不同的用户操作将会产生不同的Request类型,一般情况下我们主要有三种类型的request:CreateRequests, GroupRequests and LocationRequests.在GEF API和文档中有详细的描述。 这些request对象将用户操作对模型改变的信息巧妙地封装起来。
EditPolicies and Roles
一个EditPolicy 是EditPart 的扩展, 事实上, 和某些编辑的相对任务是EditPart 传递request给它的委托者(delegate)-EditPolicy ,类似于我们在J2EE开发中经常设计一些特定的RequestProcessor(class或method)来处理前端Servlet传过来的特定的request,。Policy是一种非常好的面向对象设计技巧,可以这么说,EditPolicy承担了绝大部分EditPart的细节工作。另外,每个EditPolicy对应一个role,为了理解EditPolicy,我们看在TablePart中的createEditPolicies()
- protected void createEditPolicies()
- {
- installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE, new TableNodeEditPolicy());
- installEditPolicy(EditPolicy.LAYOUT_ROLE, new TableLayoutEditPolicy());
- installEditPolicy(EditPolicy.CONTAINER_ROLE, new TableContainerEditPolicy());
- installEditPolicy(EditPolicy.COMPONENT_ROLE, new TableEditPolicy());
- installEditPolicy(EditPolicy.DIRECT_EDIT_ROLE, new TableDirectEditPolicy());
- }
这个方法的作用是简单地装饰TablePart的编辑功能。每一次调用installPolicy都是为EditPart注册一个EditPolicy。例如,EditPolicy.CONTAINER_ROLE是与TablePart 相关的,之所以role叫Container是因为我们知道Table包含column, 并且我们的应用程序要创建新的column以及添加这些column到已存在的table。
很多抽象的EditPolicy类提供了一个getCommand(Request request)方法的实现。在ContainerEditPolicy类中我们能够发现如下代码:
- public Command getCommand(Request request) {
- if (REQ_CREATE.equals(request.getType()))
- return getCreateCommand((CreateRequest)request);
- if (REQ_ADD.equals(request.getType()))
- return getAddCommand((GroupRequest)request);
- if (REQ_CLONE.equals(request.getType()))
- return getCloneCommand((ChangeBoundsRequest)request);
- if (REQ_ORPHAN_CHILDREN.equals(request.getType()))
- return getOrphanChildrenCommand((GroupRequest)request);
- return null;
- }
- public class TableContainerEditPolicy extends ContainerEditPolicy
- {
- protected Command getCreateCommand(CreateRequest request)
- {
- //从request得到新对象并确认它是Column的实例
- Object newObject = request.getNewObject();//从request得到新对象并确认它是
- if (!(newObject instanceof Column))
- {
- return null;
- }
- Column column = (Column) newObject;
- //得到与TablePart相关的Table对象
- TablePart tablePart = (TablePart) getHost();
- Table table = tablePart.getTable();
- //创建相关的Command并设置Table和Column信息
- ColumnCreateCommand command = new ColumnCreateCommand();
- command.setTable(table);
- command.setColumn(column);
- return command;
- }
- }
我们为不同的role有不同的EditPolicy实现。例如在我们的应用程序中TableEditPolicy继承ComponentEditPolicy来实现EditPolicy.COMPONENT_ROLE. 并通过实现createDeleteCommand(GroupRequest request)来处理REQ_DELETE.
Commands
相信了解设计模式的人都会对Command这个模式耳熟能详,每一个具体的Command负责对Model的修改,这些Command都继承GEF中的一个抽象基类:org.eclipse.gef.commands.Command,它简单地封装了我们对request的响应,其主要方法有excute(),undo(),redo(),canExcute(),canUndo(),canRedo().
大多数情况下,Command的子类需要实现excute()和undo(),而其他方法是可选的,我们可以看看ColumnCreateCommand的实现:
- public class ColumnCreateCommand extends Command
- {
- private Column column;
- private Table table;
- public void setColumn(Column column)
- {
- //为column设置名字和类型
- this.column = column;
- this.column.setName("COLUMN " + (table.getColumns().size() + 1));
- this.column.setType(Column.VARCHAR);
- }
- public void setTable(Table table)
- {
- this.table = table;
- }
- public void execute()
- {
- //将新column添加到table
- table.addColumn(column);
- }
- public void undo()
- {
- table.removeColumn(column);
- }
- }
使用Commands比起直接使用EditPolicies来改变model有两个好处:
• Command是很好的OO设计模式 ;
• Command框架支持undo和redo功能;
Command的实现不能够容纳任何对GEF特有的组件如EditParts或EditPolicies的引用。要注意保持Commands和UI逻辑干净的分离
传播机制
一旦我们改变model,我们的GEF编辑器需要将这些改变传播到UI。我们需要协调模型,视图和控制器来完成这个工作!
迄今为止,我们讨论了的GEF中Model,View和Controller的功能,但是为了做一个模型编辑器,我们需要让我们的EditPart做更多的事情:
• 需要一个listener来更新model。而model也需要传播EditPart能够接收到的事件响应
• 需要维持与其子EditPart以及Connection之间的关系,并同步其与model的改变。
• 需要更新它管理的Figures以及布局,符合model的改变。
最后要做的事情
最后我们要为这个模型编辑器定义自己的扩展点:
- <extension
- point="org.eclipse.ui.editors">
- <editor
- name="%editor.name"
- icon="icons/editor.gif"
- extensions="schema"
- class="com.realpersist.gef.editor.SchemaDiagramEditor"
- contributorClass="com.realpersist.gef.action.SchemaActionBarContributor"
- id="Schema Editor">
- editor>
- extension>
同样要为它定义一个Wizard来帮助我们创建数据库Schema图
- <extension
- point="org.eclipse.ui.newWizards">
- <category
- name="GEF (Graphical Editing Framework)"
- parentCategory="org.eclipse.ui.Examples"
- id="org.eclipse.gef.examples">
- category>
- <wizard
- availableAsShortcut="true"
- name="Schema Diagram Editor"
- icon="icons/editor.gif"
- category="org.eclipse.ui.Examples/org.eclipse.gef.examples"
- class="com.realpersist.gef.editor.wizard.SchemaDiagramWizard"
- id="com.realpersist.gef.editor.wizard.wizard.new.file">
- <description>
- Wizard to create an empty or pre-populated schema diagram file
- description>
- <selection
- class="org.eclipse.core.resources.IResource">
- selection>
- wizard>
- extension>
除了这些内容,我们还有好多东西没能在这里一一呈现,比如Palette, PropertySheet,Outline
声明:该文章已发表于《程序员》2006年第五期,如要引用请注明出处。
发表评论
-
Java程序员25个必备的Eclipse插件
2012-01-12 22:36 21926原文:http://www.fromdev.com/2012/ ... -
关于插件更新安装的错误
2007-12-21 20:12 2209在更新插件的时候出现这样的错误: Unable to comp ... -
最近做eclipse branding, features的一些经验
2007-12-16 01:24 4527知道eclipse的splash怎么做 ... -
GEF学习笔记
2007-12-07 20:20 4152GEF以前学习过, 而且还 ... -
SWT布局深入学习
2007-11-30 23:00 7940以下内容是学习"The Definitive Gui ... -
Eclipse Action 深入学习笔记(3)
2007-11-25 17:59 4080filter元素是用来指定当 ... -
Eclipse Action 深入学习笔记(2)
2007-11-25 17:14 5201Object Action 这种Action是跟弹出的上下文菜 ... -
Eclipse Action 深入学习笔记(1)
2007-11-25 17:07 7664以前做插件用到的ActionSet都只是依葫芦画瓢,没有真正理 ... -
JFace Text Editor完全掌握之终极指南(4)
2007-11-24 17:08 5671错误标识(Error Marking) Error Marki ... -
JFace Text Editor完全掌握之终极指南(3)
2007-11-24 16:56 5500内容大纲 之所以要给编 ... -
JFace Text Editor完全掌握之终极指南(2)
2007-11-24 16:53 6724最后一步就是实现各种功能 语法高亮 首先我们要实现的是语法高亮 ... -
JFace Text Editor完全掌握之终极指南(1)
2007-11-24 16:17 9986JFace Text Editor是JFace里面一个功能强大 ... -
最近的Eclipse plugin开发总结
2007-11-24 11:30 4937List控件没有提供addDblClickListener方法 ... -
eclipse3.3关于JavaFileEditorInput兼容性问题的解决
2007-11-24 11:22 4668在eclipse3.3中,JavaFileEditor ... -
Eclipse WTP Projects Facets实战指南(2)
2007-11-21 21:13 5252修饰工作 给facet在选择列表中添加图标 格式如下: xml ... -
Eclipse WTP Projects Facets实战指南(1)
2007-11-21 20:21 9583这个文章基本是"Building Project F ... -
也说关于WizardPage的动态生成
2007-11-05 14:26 5154在Eclipse中一个Wizard=Wiza ... -
关于多页编辑器中不同Editor之间的Redo&Undo冲突的解决
2007-09-03 15:17 4057在我们的插件工具的开 ... -
TextEditor原理分析笔记
2007-08-23 15:48 3376Editor的语法着色原理:Eclipse使用damage , ... -
最近的Eclipse开发总结
2007-08-23 15:46 2105java.lang.IllegalAccessError: t ...
相关推荐
3. 图形编辑器的构建:详细步骤指导如何使用GEF创建可交互的图形编辑器,包括图元的创建、布局管理、编辑操作的实现等。 4. EMF模型的生成与使用:讲解如何定义XML Schema,由EMF自动生成Java类,以及如何在代码中...
8. **实例分析**:通过实际项目案例,详细解释如何从零开始构建一个简单的模型编辑器,让学习者能动手实践。 通过这个入门系列的学习,新手开发者将能够熟练运用EMF和GEF构建高效、直观的图形用户界面和模型驱动的...
RCP是Eclipse组织提供的一种用于构建桌面应用的框架,而GEF则是用于创建图形化编辑器的工具包。本教程由法语版翻译而来,经过精心整理,以中文形式呈现,确保了国内开发者能够更方便地理解和学习。 GEF的核心概念...
GEF支持创建各种图形用户界面,包括绘图工具、流程图和模型编辑器。 GEF的主要组件包括: 1. **Model**:模型是数据结构,包含了图形元素的信息。它可以是简单的数据结构,也可以是复杂的领域模型。 2. **Edit ...
通过将GEF与EMF结合使用,可以轻松创建高度可定制的图形化编辑器,用于编辑由EMF生成的模型。 **3.3 GEF编辑器开发流程** 1. **定义模型**:首先使用EMF定义模型。 2. **创建视图**:使用GEF创建一个图形化的视图...
GEF常被用于创建系统架构图、UML模型、数据库设计工具、电路图编辑器等。它的灵活性和强大功能使其在软件工程、数据可视化和领域特定的图形编辑应用中非常受欢迎。 8. **社区支持与学习资源** Eclipse社区提供了...
通过学习和实践这些资料,开发者可以掌握构建基于 EMF 的模型,使用 GEF 创建图形编辑器,以及如何将 XML Schema 数据与模型集成。这些技术在现代软件工程,尤其是企业级应用和工具开发中,都有着广泛的应用。
1. **模型(Model)**:在GEF中,模型是数据结构的抽象,它定义了编辑器所操作的对象和它们之间的关系。模型独立于视图和控制器,是应用程序的核心部分。 2. **视图(View)**:视图是模型的可视化表示,由GEF提供...
而GMF则是对GEF的增强,专门用于创建复杂的模型驱动的图形编辑器。在Eclipse 3.2这个版本中,这些工具集成了良好的图形建模和可视化编辑能力,对于开发人员来说,它们是构建图形化应用程序和模型的重要工具箱。 ...
### GEF快速入门教程与EMF教程概览 #### GEF HelloWorld 示例详解 ...此外,还介绍了如何设置项目依赖、创建编辑器以及实现GEF的基本组件。这些步骤不仅适用于本教程的示例,也是构建更复杂图形编辑器的基础。
通过这个GEF入门系列,你可以逐步掌握如何利用GEF创建强大的图形化编辑器,无论是简单的绘图工具还是复杂的业务流程编辑器,GEF都能提供坚实的技术支持。在实践中不断探索和学习,你将能够充分发挥GEF的潜力,构建出...
**GEF(Graphical Editing Framework)开发指南*...总之,"GEF_Tutorial.rar"是一个宝贵的资源,它将引导你踏入GEF开发的世界,通过实例学习,你将能够熟练地创建出功能丰富的图形编辑器,实现各种复杂的图形用户界面。
GEF是一个强大的开源库,允许开发者创建富客户端应用,特别是那些需要交互式图形界面的领域,如流程图、网络拓扑图或数据库模型。 这个SDK包含了用于开发图形用户界面的所有必要组件,包括模型-视图-控制器(MVC)...
GEF是Eclipse平台下开发图形化编辑器的强大工具,它通过提供模型、视图、编辑部件、命令和布局等组件,降低了创建图形界面的复杂度。通过深入理解和熟练应用GEF,开发者可以高效地构建出功能丰富的图形化应用,满足...
通过深入研究这些DEMO,开发者可以掌握使用GEF构建图形化编辑器的基本技能,进一步了解如何利用Java和Eclipse平台创建复杂的图形用户界面。每个DEMO都是一个独立的学习单元,通过实践和比较,可以更全面地理解GEF的...
4. 示例代码和项目:可能包括了使用EMF、SWT和GEF创建的示例应用程序或编辑器,帮助开发者理解如何结合使用这些技术。 5. 文档和教程:详细介绍了如何使用这三个框架,包括API参考、用户指南和最佳实践。 通过学习...
2. **在ViewPart中使用GEF**:通常情况下,GEF主要用于创建图形编辑器(Editor),但本示例特别指出在非Editor的ViewPart中使用GEF。ViewPart是Eclipse RCP(Rich Client Platform)中的一个组件,用于显示各种视图...
在Eclipse插件开发中,GEF(Generic Editor Framework)是一种用于构建图形化编辑器的框架,它允许开发者创建复杂的图形界面,特别适合构建模型编辑器。EMF(Eclipse Modeling Framework)是Eclipse项目中的一个重要...
- **模型(Model)**:在GEF中,模型是数据结构的核心,它存储了编辑器所表示的信息。模型独立于图形视图,可以采用任何适合的数据结构实现。 - **视图(View)**:视图是模型的可视化表示,它将模型数据转换成用户...