在GMF帮我们生成的应用程序里,画布(Canvas)的布局缺省是使用XYLayout的,这种布局适合UML类图、流程图等应用,但并不适合序列图或表格这类应用。而且目前GMF的.gmfgraph模型里没有提供为整个Canvas设置布局的地方,因此只能通过修改代码的方式实现。因为GMF Runtime是基于GEF的,即GMF生成的代码本质上也是一个GEF应用程序,所以根据以往编写GEF应用程序的经验,不难找到需要修改的地方。
首先要修改作为画布的那个EditPart(下称yourCanvasEditPart),这个类是从gmf的DiagramEditPart继承过来的,看一下后者的createDefaultEditPolicies()方法就会发现它的LAYOUT_ROLE的EditPolicy是gmf的XYLayoutEditPolicy:
installEditPolicy(EditPolicy.LAYOUT_ROLE, new XYLayoutEditPolicy());
GEF里同一个EditPart上要覆盖一个已有EditPolicy的方法是使用同样的Role安装新的EditPolicy,所以我们应该在yourCanvasEditPart的createDefaultEditPolicies()方法里使用LAYOUT_ROLE安装自己的EditPolicy,这里为方便使用了GEF提供的FlowLayoutEditPolicy,你若有特殊需要可实现自己的EditPolicy:
installEditPolicy(EditPolicy.LAYOUT_ROLE, new FlowLayoutEditPolicy() { @Override protected Command getCreateCommand(CreateRequest request) { return null; } @Override protected Command createMoveChildCommand(EditPart child, EditPart after) { return null; } @Override protected Command createAddCommand(EditPart child, EditPart after) { return null; } @Override protected boolean isHorizontal() { return true; } });
我们知道,GEF里每个EditPart上作为LAYOUT_ROLE安装的EditPolicy应该和此EditPart对应的Figure使用的LayoutManager匹配,例如XYLayoutEditPolicy对应XYLayout,而FlowLayoutEditPolicy匹配的LayoutManager就是FlowLayout或ToolbarLayout,这两个LayoutManager最大的区别是前者允许子图形换行(列)排列,而后者只能有一行(列)。要注意一点,FlowLayoutEditPolicy与ToolbarLayout一起使用存在一点问题,原因是在FlowLayoutEditPolicy的isHorizontal()方法里认为传入的layoutmanager参数是FlowLayout,因此我们在上面代码里覆盖了isHorizontal()方法,至于返回true或false根据你的需求决定。
现在,为了匹配修改后使用的FlowLayoutEditPolicy,我们要覆盖yourCanvasEditPart的createFigure()方法,在父类DiagramEditPart里这个方法返回的Figure使用的是FreeFormLayout,我们现在需要的是ToolbarLayout,所以:
protected IFigure createFigure() { Figure f = new FreeformLayer(); ToolbarLayout layout = new ToolbarLayout(); layout.setVertical(false); layout.setSpacing(10); layout.setStretchMinorAxis(true); f.setLayoutManager(layout); f.setBorder(new MarginBorder(15)); return f; }
经过这样两处修改后,你的编辑器应该已经像下图所示这样了(可能还有些细节代码需要处理一下):
GMF在GEF基础上做了很多包装,例如添加了SemanticEditPolicy、CanonicalEditPolicy等等新的EditPolicy,以及相关的很多Command和EditPart,它们为GMF应用程序提供了新的功能,虽然掌握GMF Runtime的API需要花些时间,但这允许我们在不进行大规模编写代码的情况下获得符合需求的图形化编辑器,建议先提前了解一下。
Update(2007/07/17): 在GMF 2.0里,可以通过设置xxx.gmfgen文件里Figure Viewmap的"Layout Type"属性为"TOOLBAR_LAYOUT"达到同样目的。