﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-很久很久以前-随笔分类-RCP</title><link>http://www.blogjava.net/pandawang/category/6829.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 04:17:35 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 04:17:35 GMT</pubDate><ttl>60</ttl><item><title>基于RCP的GEF编辑器中RetargetAction的注册问题</title><link>http://www.blogjava.net/pandawang/archive/2006/08/19/64532.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Sat, 19 Aug 2006 09:35:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2006/08/19/64532.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/64532.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2006/08/19/64532.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/64532.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/64532.html</trackback:ping><description><![CDATA[最近做的gef编辑器在删除时遇到了一些问题,就是不能通过delete键删除,到处搜集资料,解决了,<br />首先需要在相应rcp工程中的ActionBarAdviser类中注册相应的Action,比如对应于deleteAction,我在方法org.eclipse.ui.application.ActionBarAdvisor#makeAction(IWorkbenchWindow)中注册deleteAction,如下:<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id="Codehighlighter1_56_144_Open_Image" onclick="this.style.display='none'; Codehighlighter1_56_144_Open_Text.style.display='none'; Codehighlighter1_56_144_Closed_Image.style.display='inline'; Codehighlighter1_56_144_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_56_144_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_56_144_Closed_Text.style.display='none'; Codehighlighter1_56_144_Open_Image.style.display='inline'; Codehighlighter1_56_144_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> makeAction(</span><span style="COLOR: #0000ff">final</span><span style="COLOR: #000000"> IWorkbenchWindow window)</span><span id="Codehighlighter1_56_144_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_56_144_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    IAction delAction </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> ActionFactory.DELETE.create(window);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    register(delAction);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span></div><br />只是这么设置还是不能删除相应的图形元素,需要在相应的编辑器中重载init方法,添加如下的代码<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id="Codehighlighter1_80_378_Open_Image" onclick="this.style.display='none'; Codehighlighter1_80_378_Open_Text.style.display='none'; Codehighlighter1_80_378_Closed_Image.style.display='inline'; Codehighlighter1_80_378_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_80_378_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_80_378_Closed_Text.style.display='none'; Codehighlighter1_80_378_Open_Image.style.display='inline'; Codehighlighter1_80_378_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> init(IEditorSite site, IEditorInput input) </span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> PartInitException </span><span id="Codehighlighter1_80_378_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_80_378_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> TODO Auto-generated method stub</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">super</span><span style="COLOR: #000000">.init(site, input);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    ActionRegistry registry </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> getActionRegistry();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    IActionBars bar </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> site.getActionBars();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    String id </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> ActionFactory.DELETE.getId();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    bar.setGlobalActionHandler(id,registry.getAction(id));<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    bar.updateActionBars();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span></div><br />在这里仔细研究会发现,在第一段代码中实际上时创建了一个action,这是一个RetargetAction,而在super.init()方法会调用一个createAction方法,这里创建的是gef默认的redoAction undoAction selectionAction deleteAction saveAction.需要注意的是RetargetAction是一种可以跟踪当前活动的部分,由于retargetAction含有一个id,如果这个活动部分提供的handler的id和retargetAction的id相同,那么相应的对retargetAction的调用就转嫁成对当前这个活动部分的handle的调用,(当然如果根本就没有handle,那么这个action会disable).所以,我们可以看出来,这个retargetAction会在gef编辑器激活后调用gef的deleteAction.<img src ="http://www.blogjava.net/pandawang/aggbug/64532.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2006-08-19 17:35 <a href="http://www.blogjava.net/pandawang/archive/2006/08/19/64532.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个用RCP实现的简单的GEF程序</title><link>http://www.blogjava.net/pandawang/archive/2006/01/12/27754.html</link><dc:creator>Long Long Ago</dc:creator><author>Long Long Ago</author><pubDate>Thu, 12 Jan 2006 06:35:00 GMT</pubDate><guid>http://www.blogjava.net/pandawang/archive/2006/01/12/27754.html</guid><wfw:comment>http://www.blogjava.net/pandawang/comments/27754.html</wfw:comment><comments>http://www.blogjava.net/pandawang/archive/2006/01/12/27754.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/pandawang/comments/commentRss/27754.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/pandawang/services/trackbacks/27754.html</trackback:ping><description><![CDATA[uo &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最近在学习GEF，本例子主要是修改了<A href="http://bjzhanghao.cnblogs.com/archive/2005/02/19/106000.html">八进制</A>的例子。在这里做一下总结。先来介绍一下gef，网上关于GEF的介绍越来越多，从另一方面也说明这个技术确实在热起来，不过GEF为了实现可扩放性和可重用性，做的很是复杂（闲话一下，最近看了一本书《Better.Faster.Lighter.Java》，没看多少，Justin Gehtland, Bruce A. Tate写的，一开始就说了，为了满足越来越多的需要，各种framework，library，language都是越来越复杂了，学习曲线也变得陡峭了，这个似乎是无法避免的，java语言也是，不信去看看jdk，1.1时才3.7MB，1.4时已经38MB了。我也一直坚信，Simply the best，呵呵）。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GEF的一些资源： <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1。<A href="http://www.eclipse.org/">www.eclipse.org</A> 这个是源头啊，faq也可以看看&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2。ibm的dW 除了相关文章，这里还有本关于gef和emf的红宝书，可以<A href="http://http://publib-b.boulder.ibm.com/Redbooks.nsf/RedbookAbstracts/sg246302.html">免费下载</A>。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3。eclipseworld.org 这个是一个关于eclipse中文社区 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4。八进制的blog http://bjzhanghao.cnblogs.com/ 。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5。这里还有些中文教程 http://www.benisoft.com/cn/index.htm<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6。还有一些blog <A href="/hopeshared/">http://www.blogjava.net/hopeshared/</A>&nbsp; <A href="/eclipshine/">http://www.blogjava.net/eclipshine/</A>&nbsp;<A href="/reloadcn/">http://www.blogjava.net/reloadcn/</A>&nbsp;<A href="/USTCEric">http://www.blogjava.net/USTCEric</A><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 好了，现在来介绍一下GEF的实现机制，主要是我的一些理解可能还有一不对的地方，欢迎大家帮我改正。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GEF是具有标准MVC（Model-View-Control）结构的图形编辑框架，其中Model由我们自己根据业务来设计，它要能够提供某种模型改变通知的机制，用来把Model的变化告诉Control层；Control层由一些EditPart实现，EditPart是整个GEF的核心部件；而 View层，大多数情况下，使用Draw2D实现了，其作用是把Model以图形化的方式表现给使用者，当然你也可以使用其他图形包，不过gef与 Draw2D的结合还是非常紧密的，一般为了使用方便，View都是使用Draw2D实现的。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 关于Draw2D，八进制有一篇相应的<A href="http://http://bjzhanghao.cnblogs.com/archive/2005/02/09/103595.html">文章</A>，还有eclipse上的一篇<A href="http://www.eclipse.org/articles/Article-GEF-Draw2d/GEF-Draw2d.html">文章</A>，可以参考，这里有几点需要强调一下：<BR>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1。Draw2D提供了很多缺省图形，最常见的有三类：1、形状（Shape），如矩形、三角形、椭圆形等等；2、控件（Widget），如标签、按钮、滚动条等等；3、层（Layer），它们用来为放置于其中的图形提供缩放、滚动等功能。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2。每个图形都可以拥有一个边框（Border），Draw2D所提供的边框类型有GroupBoxBorder、TitleBarBorder、ImageBorder、 ButtonBorder，以及可以组合两种边框的CompoundBorder等等，在Draw2D里还专门有一个Insets类用来表示边框在图形中所占的位置，它包含上下左右四个整型数值。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3。一个图形可以包含很多个子图形，这些被包含的图形在显示的时候必须以某种方式被排列起来，负责这个任务的就是父图形的LayoutManager，相应的约束（Constraint）对象就在这里，比如在子图形刷新（refreshVisuals）时可以通过将其布局约束传递给其父元素来定位。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4。利用Draw2D中的Router、Anchor和Locator，可以实现多种连接样式。Router负责连接线的外观和操作方式；Anchor控制连接线端点在图形上的位置，即"锚点"的位置；Locator的作用是定位图形。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 前面说过了GEF是通过MVC架构实现的，下面分别介绍这三个方面：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一、模型（Model）：这个是相对比较容易理解，模型保存着业务逻辑，他是GEF这中唯一可以持久化的，并且需要提供相应的监听机制，来通知 EditPart去更新View，监听机制又可以分为分布式和集中式两种，我们可以针对域监听器进行转有通知，也可以全局广播；在这里我们认为 Command（EditPart用来更新模型的对象）也是模型的一个部分，因为它了解模型。此外，在有时候可能需要多种模型。我们对于业务模型，提供一个“视图”模型，这样便于实现和满足相应的要求，不管内部模型是怎么样的，都要实现通知机制。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 二、视图。GEF提供了在EclipseWorkbench中使用Viewer，称为EditPartViewer。它的作用和jface中的 Viewer很相，不过这时候它的ContentProvider和LabelProvider是EditPart，通过setContents设置（注意在八进制代码中setContents参数为模型对象，通过分析发现，在AbstractEditPartViewer中此方法被重载，可以除了接受 org.eclipse.gef.editpart对象外可以接受Object对象，不过此时回调用EditPartFactory，通过给定的模型对象来创建相应的EditPart，个人认为这样做并不与“View与Model无直接联系”的要求相矛盾）。这个接口继承了 org.eclipse.jface.viewers.ISelectionProvider接口（这个也和jface中的viewer一样），因此使 viewer提供了监听器，这样可以将对view的操作传递到editpart。EditPartViewer会维护各个EditPart的选中状态，如果没有被选中的EditPart，则缺省选中的是作为contents的EditPart。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EditPartViewer可以适配到任何一个SWT控件，因为它要求有createControl方法，接受一个父SWT控件作为适配对象，从而将 GEF生成的Figure对象显示在这个SWT控件上，因此GEF可以使用任何图形包，不过GEF提供了对Draw2D的默认实现，比如 AbstractGraphicalEditPart类中的回调方法createFigure就要求返回一个IFigure对象。将一个GEF图形显示出来可以使用org.eclipse.ui.part.EditorPart也可以是org.eclipse.ui.part.ViewPart，如果使用 EditorPart，则需要实现继承自WorkbenchPart的createPartControl,如果是ViewPart则需要自己实现与 GEF的交互，不过Eclipse Workbench对viewpart和editorpart的支持是一样的，都是在plugin文件扩展相应的扩展点。一般来说，使用GEF对 Editorpart的模式实现是非常方便的。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GEF目前提供两种视图分别是GraphicalViewer和TreeViewer，都间接继承了EditPartViewer接口，前者利用 Draw2D图形（IFigure）作为表现方式，多用于编辑区域，后者则多用于实现大纲展示，并且他们有两个具体的实现，分别是 ScrollingGraphicalViewer和TreeViewer。其中ScrollingGraphicalViewer，通过分析GEF源代码可知，是GraphicalEditor中Viewer的默认实现，我们可以通过GraphicalEditor类提供的 setGraphicalViewer(GraphicalViewer)方法重新设置其他viewer。我们在使用的时候通过 configureGraphicalViewer和initializeGraphicalViewer方法来配置GraphicalViewer。所不同的是，在configureGraphicalViewer之后initializeGraphicalViewer之前插入了一个 hookGraphicalViewer方法，其作用是同步选择和把 EditPartViewer作为SelectionProvider注册到所在的site，使其成为SelectionProvider。<BR>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;此外，GEF中还提供一种成为调色板（PaletteViewer）的视图，它也是间接实现了EditPartViewer接口。因此，我也像配置GraphicalViewer一样来配置PaletteViewer，类似的使用 configurePaletteViewer和initializePaletteViewer方法，其间类似的插入了一个 hookPaletteViewer方法，用于设置相应EditDomain的PaletteViewer。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最后，总结一下如何配置GraphicalView，主要是四个方面：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1。设置一个RootEditPart：RootEditPart的是使整个GEF框架运行起来的关键之一。RootEditPart并不对应于任何的模型对象，它将从setContents()方法中接收到的模型对象进行转换，并添加到整个的EditPart体系中去。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2。设置其EditPartFactory：负责从模型到EditPart的转换。一般来说一个模型对象对应于一个EditPart。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3。设置EditDomain：用来接收事件并选择恰当的事件处理函数进行处理，这个主要是为了相应view所接收到的用户的操作。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4。调用setContents()方法：为其设置要显示的内容。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 三、控制器（EditPart）。这是GEF最核心的地方了，它将model和view联系起来。程序员可以继承三种EditPart，分别是 org.eclipse.gef.editparts.<B>AbstractGraphicalEditPart</B>，org.eclipse.gef.editparts.<B>AbstractConnectionEditPart</B>（AbstractGraphicalEditPart的子类）和org.eclipse.gef.editparts.<B>AbstractTreeEditPart。</B>EditPart 的生命周期当setContents时，将模型对象输入，此对象为顶层对象，通过它可以遍历所有的模型对象。：EditPartViewer配备有 EditPartFactory，EditPartViewer通过EditPartFactory构造相应的Contents EditPart。然后EditPartViewer中的每个EditPart通过EditPartFactory构造相应的子EditPart。当用户添加新的模型的时候，包含这些模型对象的所对应的EditPart将构造相应的EditPart作出相应。视图的构造和EditPart的构造是同时进行的，每当EditPart构造并添加到它的父EditPart后相应的view也做同样的事情，比如GraphicalEditor中就有 GraphicalViewer成员变量，在此edipart创建时回调用createPartControl，在这个方法中将会创建相应的view，并将其加入到父view中。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一旦用户丢弃了某些模型对象，相应的EditPart就会被丢弃。比如用户执行了删除操作，则相应的模型对象和相应的EditPart都被删除了，但用户撤销了删除操作而重新创建的EditPart与原来的EditPart是不同的，所以EditPart是不能保存长期信息的，应该交给模型去保存，并且 EditPart也是不能被Command所引用。<BR>&nbsp;&nbsp;&nbsp; 在具体使用时，应该先定一个Contents EditPart,它的父元素为EditPartViewer的RootEditPart。RootEditPart是EditPartView的 root，它将EditPartView和它的contents（一般认为是顶层模型对象所对应的EditPart）联系起来，RootEditPart 为用户的EditPart提供一致性的上下文（context）。并且，当没有被选中的模型EditPart时，顶层对象的EditPart是默认被选中的，而RootEditPart是不能被选中的或者定位的，甚至不能与用户相交互，他也就没有对应的模型对象。GEF提供了几个默认的 RootEditPart的实现：FreeformGraphicalRootEditPart,RootTreeEditPart, ScalableRootEditPart，ScalableFreeformRootEditPart（此类继承于 FreeformGraphicalRootEditPart，增加了缩放Zoom支持，提供了ZoomManager；增加了一个LayerPane： ScalableFreeformLayeredPane。），（原来还有个GraphicalRootEditPart，已经deprecated，用 ScalableRootEditPart代替）。这里要注意的是：<BR>&nbsp;&nbsp;&nbsp; 1)对于FreeformRootEditPart（以及它的子类 ScalableFreeformRootEditPart），它的Contents EditPart应该有一个<FONT size=-1>org.eclipse.draw2d</FONT>.<B>FreeformFigure</B>对象（比如FreeformLayer或FreeformLayeredPane）作为它的Figure。例如在我们的代码里，对应的就是在 DiagramPart中的createFigure方法，它返回了一个FreeformLayer对象。<BR>&nbsp;&nbsp;&nbsp; 2) FreeformGraphicalRootEditPart的Primery Layer没有使用draw2d的LayoutManager，并且，除非contents的figure是个freeform figure，否则不能正确的调整大小。<BR>&nbsp;&nbsp;&nbsp; 3)FreefromGraphicalRootEditPart使用FreeformViewport类作为它的primary figure，这个类必须和ScrollingGraphicalViewer使用。<BR>&nbsp;&nbsp;&nbsp; 4)ScalableRootEditPart使用 Viewport作为primery figure，这个类必须和ScrollingGraphicalViewer使用。<BR>&nbsp;&nbsp;&nbsp; 5)RootTreeEditPart是TreeViewer的RootEditPart。<BR>&nbsp;&nbsp;&nbsp; Contents EditPart的图形一般是一个空面板，该面板将包含diagram的子图。<BR>&nbsp;&nbsp;&nbsp; 我们还要定义其他“视图”模型的EditPart，比如节点（node），连接（connection）。对于节点，是Graphical，可以继承 AbstractGraphicalEditPart。并且可以实现NodeEditPart接口，则可以支持源和目标的 ConnectionEditPart，使用Anchor，具体在下面有讲述。在这里，我们的代码的NodePart类中，重载了 refreshVisual方法，其中设置figure的布局约束是通过它的父元素来定位的，我不知道这是不是标准的方法，XYLayout使用的是 rectangle约束，如果长宽设为－1，表示为该图形提供理想大小。不要使用setBounds，XYLayout布局管理器可以保证对滚动条进行更新，并能将相对约束转化为绝对约束，如果长宽设置为－1，则能够将图形设置为理想的大小。此外，为了改进性能，我们可以将refreshVisual中有若干模型的分别刷新，或者设置是否需要刷新的开关。<BR>&nbsp;&nbsp;&nbsp; 对于连接，可以继承AbstractConnectionEditPart，这个抽象类已经实现了 ConnectionEditPart。和Node实现一样，通过refreshVisual方法将属性从模型映射到图形。连接也可以有约束，不过与前面的约束不尽相同。在这里，连接路由器（connection router）使用约束来是连接转向（bend）。需要注意的是，一个Connection EditPart的图形必须是一个draw2d的Connection，这样就引入了连接锚（Connection Anchor）。连接必须由连接锚（ConnectionAnchor）“锚定”在两端。因此，需要在连接EditPart或者节点EditPart中实现使用什么样的锚。缺省情况下，GEF使用节点EditPart通过实现NodeEditPart接口来提供锚。这是因为，锚的选择取决与各个节点上正在使用的图形，而连接EditPart不应了解节点上的图形，并且，当用户创建连接的时候，连接EditPart并没有创建，这时候就由节点自己显示反馈。这里需要注意的是：何时使用以及何时不使用ConnectionEditPart，当用户可以选择某些东西并可与之交互时，就需要 ConnectionEditPart。它可能与某行中的某个对象相对应，并且回自己删除；如果这是需要一个绘制直线的节点或者容器，那么只需要用图形的 paint方法绘制直线，或者组合一个图形，这个图形包含Polyline图形。连接必须要拥有源和目标。如果要创建一个连接，并且在没有源和目标存在的情况下，可以继承AbstractGraphicalEditPart，并使用连接图形，比如PolylineConnection。<BR>&nbsp;&nbsp;&nbsp; 正如前面说的，模型需要实现某种通知机制，各个EditPart要将自己做为监听者，注册在模型上，以便在模型发生改变的时候收到相应的通知。 &nbsp; 当EditPart收到相应的通知时，调用相应的处理方法，来进行一次强制的刷新，对于模型对象的增减可以调用refreshChildren方法，对于简单属性的更改可以调用refreshVisuals方法，这时，像前面提到的，可以只刷新改变的部分，以提高性能。一般，我们在Activate方法中注册监听器，在Deactivate方法中注销监听器。<BR>&nbsp;&nbsp;&nbsp; 以上完成的是从模型到视图的映射，你还需要实现的是编辑策略Edit Policies，因为EditPart并不直接对模型进行编辑，每一个EditPolicy都针对一个特定的编辑任务或者一组相关的工作。这样的实现便于在不同的EditPart间重用（reuse）编辑行为，并且这样的实现，可以动态的改变行为，比如改变layout或者routing时。在 createEditPolicies方法中，我们要insall我们的的Policies，这时候就需要roles，roles的作用就是作为关键字来标示不同的policies。policy中提供Command，每个应用程序都有个Command栈，Command的运行要通过Command栈，而不是直接调用execute方法。<BR>&nbsp;&nbsp;&nbsp; 说到这里，要注意EditPartView是视图的，一般放在一个UI插件上比如EditorPart，viewPart，甚至swt控件。EditPart是控制器，联系视图和模型。<BR>&nbsp;&nbsp;&nbsp; 在本文的最后介绍一下GEF的运行机制：EditPartView接受用户的操作，如节点的移动，增删，每个节点对应一个EditPart对象，每个 EditPart都有一组由Role区分的EditPolicies，每个EditPolicy会对应一些Command对象，Command最终会对模型进行操作。用户的操作会转化为Request分配给特定的EditPolicy，由EditPolicy创建相应的Command对模型进行操作，这些 Command会保留在EditDomain的命令堆栈中，用于实现undo，redo功能，EditDomain是专门用于维护 EditPartView，Command信息的对象，一般每个EditPart有一个EditDomain。<BR>&nbsp;&nbsp;&nbsp; 以上就是对所作的GEF部分的大概描述，可能有些地方写的比较罗嗦，有的地方写的也可能不对，希望大家指出，谢谢。下面还要对RCP部分进行一些描述。<BR><img src ="http://www.blogjava.net/pandawang/aggbug/27754.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/pandawang/" target="_blank">Long Long Ago</a> 2006-01-12 14:35 <a href="http://www.blogjava.net/pandawang/archive/2006/01/12/27754.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>