最后轮到GEF中最重要的Controller——控制器了。它们是model和view之间的桥梁。我们先从直观上来分析这种连接作用。
1 Connection <-->ConnectionEditPart <-->PolylineConnection
2 EllipticalShape <-->ShapeEditPart <-->Ellipse
3 RectangularShape <-->ShapeEditPart <-->RectangleFigure
4 ShapeDiagram <-->DiagramEditPart <-->FreeformLayer
再看一个图:
先分析一下ShapeEditPart类。
class ShapeEditPart extends AbstractGraphicalEditPart
implements PropertyChangeListener, NodeEditPart
它继承自AbstractGrahpicalEditPart,同时实现了PropertyChangeListener和NodeEditPart。
AbstractGrahpicalEditPart 是一个非常重要的类,是GEF中控制器的核心。既然它是模型和视图的桥梁。那么猜想一下它一定知道模型是什么、视图在哪里。看一下它的成员变量:
1 figure:IFigure 视图表现,在createFigure()中初始化;
2 model:Object 模型,由EditPartFactory传递给EditPart;
3 parent:EditPart 父亲EditPart,EditPart的父子关系由model决定;
4 children:List 子EditPart
5 sourceConnections:List 源连接模型对应的EditPart
6 targetConnections:List 目的连接模型对应的EditPart
7 policies:Object[] 策略,稍后再议。
这里就很明了,在EditPartFactory中,根据模型来产生EditPart,然后在EditPart中的createFigure()创建图形,再通过一系列的方法刷新显示(refreshVisuals()、refreshChildren()等)。
先看看EditPartFactory的实现——ShapesEditPartFactory.java:
核心就是getPartForElement()方法了,也就是根据模型创建EditPart(控制器)了。
它实现了PropertyChangeListener,这个接口只有一个方法,propertyChange()。上面我们在讲Connection.java的时候,说
有行代码:
它将线条样式这个属性的变更通知给属性监听器,要求它做一些处理。这里ShapeEditPart就是一个属性监听器,它接收到传递过来的属性变更信息,然后做出一些处理,见:
至此ShapeEditPart将模型与视图关联到了一起,模型的改动将带来视图的改动,这个过程是自动的。
在ShapeEditPart的初始化过程中,有几个方法比较重要:
1 activate():EditPart被激活的操作,包括激活所有子EditParta以及给对应的模型添加属性监听器;
同时请注意在deactivate()中进行的remove操作。
2 createEditPolicies():安装编辑策略,这与图形编辑器是否提供可视化的操作相关,比如拖拽、创建、删除;
3 createFigure():创建视图图形元素。
<!--
/* Font Definitions */
@font-face
{font-family:Wingdings;
panose-1:5 0 0 0 0 0 0 0 0 0;
mso-font-charset:2;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:0 268435456 0 0 -2147483648 0;}
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-alt:SimSun;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;
mso-font-charset:1;
mso-generic-font-family:roman;
mso-font-format:other;
mso-font-pitch:variable;
mso-font-signature:0 0 0 0 0 0;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;
mso-font-charset:0;
mso-generic-font-family:swiss;
mso-font-pitch:variable;
mso-font-signature:-1610611985 1073750139 0 0 159 0;}
@font-face
{font-family:"/@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-unhide:no;
mso-style-qformat:yes;
mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
font-size:10.5pt;
mso-bidi-font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:宋体;
mso-fareast-theme-font:minor-fareast;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;
mso-font-kerning:1.0pt;}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
{mso-style-priority:34;
mso-style-unhide:no;
mso-style-qformat:yes;
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
text-indent:21.0pt;
mso-char-indent-count:2.0;
mso-pagination:none;
font-size:10.5pt;
mso-bidi-font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:宋体;
mso-fareast-theme-font:minor-fareast;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;
mso-font-kerning:1.0pt;}
.MsoChpDefault
{mso-style-type:export-only;
mso-default-props:yes;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;}
/* Page Definitions */
@page
{mso-page-border-surround-header:no;
mso-page-border-surround-footer:no;}
@page Section1
{size:612.0pt 792.0pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;
mso-header-margin:36.0pt;
mso-footer-margin:36.0pt;
mso-paper-source:0;}
div.Section1
{page:Section1;}
/* List Definitions */
@list l0
{mso-list-id:1664896968;
mso-list-type:hybrid;
mso-list-template-ids:1525981020 67698713 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
@list l0:level1
{mso-level-number-format:alpha-lower;
mso-level-text:"%1/)";
mso-level-tab-stop:none;
mso-level-number-position:left;
margin-left:42.0pt;
text-indent:-21.0pt;}
ol
{margin-bottom:0cm;}
ul
{margin-bottom:0cm;}
-->
还有一些其他比较重要的方法,如下:
a) getModelSourceConnections() :与连接有关,返回对应模型的源连接;
b) getModelTargetConnections() :与连接有关,返回对应模型的目的连接;
c) getSourceConnectionAnchor(ConnectionEditPart connection) :获取源连接的锚点,也就是连接与图形的焦点位置,详细见后面 ConnectionEditPart 的讲解;
d) getSourceConnectionAnchor(Request request) :获取源连接的锚点,这个锚点与 Request 相关,详细见后面 Policy 的讲解部分;
e) getTargetConnectionAnchor(ConnectionEditPart connection) :获取目的连接的锚点,也就是连接与图形的焦点位置,详细见后面 ConnectionEditPart 的讲解;
f) getTargetConnectionAnchor(Request request) : 获取目的连接的锚点,这个锚点与 Request 相关,详细见后面 Policy 的讲解部分;
在org.eclipse.gef.examples.shapes.parts下还有一部分是AbstractTreeEditPart的继承类,这些类用于在Outline 视图中显示大纲的。它们同样由EditPartFactory控制:
本文深入探讨了GEF框架中控制器的核心作用,特别是ShapeEditPart如何作为模型与视图间的桥梁,实现模型变化与视图更新的自动同步。
3156

被折叠的 条评论
为什么被折叠?



