GMF 界面知识点

来源:互联网 发布:手机版网络维护软件 编辑:程序博客网 时间:2024/05/17 06:01

专注于EMP以及DSLs的技术宏观视图。理解项目与组件整合基础。



GMF界面若干知识点的整理,主要实现了一个树型的自动布局。


提供几个参考文献地址:

EMF与DSLs http://www.cnblogs.com/zhoujg/archive/2010/10/20/1855510.html 
http://www.uml.org.cn/zjjs/200807315.asp 
XSD文件简介http://www.w3school.com.cn/schema/schema_example.asp 
规范XML文件的定义文件。

Eclipse IDE for Java and DSL Developers下载http://www.eclipse.org/downloads/packages/eclipse-ide-java-and-dsl-developers/keplerr 

以下为实例
定义ECORE模型如图所示:

对于Topic与subTopic在模型中,有两种关联方式,一种是自身的通过subtopics关联,另一种通过Relationship这个实体类来关联。查看最终实现如下图所示:


如图t1,t2间的联系是通过topicSubtopics,而t2,t3间的联系是通过Relationship,查看属性可得:

需要注意是的是对于Relationship的实现在利用teneo实现数据保存时,是作为单独的一个表存储的。从上面的模型文件中看到对于RelationShip中有属性Type,这个type定义了三种不同的关联关系,分别为Dependency,Include,Extend.升级后如图所示:


这样需要在gmftool中定义三个tool,同时在gmfmap中定义三个linkMapping.


注意在linkMapping中加入了Constraint,这样就可以限定此联结的类型。

在gmftool中根据Type类型,添加3个新的tool,而在gmfmap中引用这三个,并设置显示方式。如上图:
首先会显示两个label分别对应type和name.
对于第一个Constraint属性解释是This enables us to identify each of our  Relationship mappings so that the generator can create code to distinguish nodes based on their type attribute. 

可以看到,我们修改了以下几处
1.矩形修改成了圆角矩形
2.Relationship的联系并成了虚线且有箭头
3.Relationship上添加了属性图标
4.Topic上name的图标被去掉
注意,关系中类型均为大写如EXTENED,这是因为在设计模型的时候,对于属性literal,采用默认名称的结果。可以在模型中修改为小写,或仅用首字母代替。

Rounded Rectangle的Corner Height/Corner Width可以指定圆角的度数。Line kind可以指定线的类型。
Insets表示对里面的图形设置边距
Node Topic的Default Size Facet可以指定默认大小。
Diagram Label中的Element Icon表示是否显示图标。



这是修改TopicFigure布局之后的效果。即居中显示。自定义布局。可参考《SWT学习02自定义布局》

this.setLayoutManager(new StackLayout() {public void layout(IFigure figure) {Rectangle r = figure.getClientArea();/** 获得所有控件 */List children = figure.getChildren();IFigure child;Dimension d;for (int i = 0; i < children.size(); i++) {child = (IFigure) children.get(i);/** * getPreferedSize方法是获取组的首选大小, 因为布局管理器会根据组件自动调整框架窗口的大小, * 可以通过这个方法来获取自动调整后的组件大小 */d = child.getPreferredSize(r.width, r.height);d.width = Math.min(d.width, r.width);d.height = Math.min(d.height, r.height);Rectangle childRect = new Rectangle(r.x+ (r.width - d.width) / 2, r.y+ (r.height - d.height) / 2, d.width, d.height);child.setBounds(childRect);}}});
同理,考虑将整个图形按label中的字长度真正居中显示。如图:



只需要简单修改上面代码即可。

//获得文本的长度Rectangle txt=((WrappingLabel)child).getTextBounds();Rectangle childRect = new Rectangle(r.x+ (r.width - txt.width) / 2, r.y+ (r.height - txt.height) / 2, txt.width, txt.height);

自定义装饰


首先自定义一个装饰类,稍后在gmfgraph中,添加一个自定义的Decoration设置Qualified Class Name,再在相应的Connection设置Source Decoration或Target Decoration。
最主要的还是装饰类的编写:
package org.eclipse.mindmap.diagram.figures;import org.eclipse.draw2d.Ellipse;import org.eclipse.draw2d.Graphics;import org.eclipse.draw2d.RotatableDecoration;import org.eclipse.draw2d.geometry.Point;import org.eclipse.draw2d.geometry.Rectangle;import org.eclipse.draw2d.PolygonDecoration;/*** * 此继承自Ellipse此为一个椭圆 * @author Administrator *RotatableDecoration-An IFigure that can be rotated. *PolygonDecoration-A rotatable, polygon shaped decoration most commonly used for decorating the ends of polylines. *PolylineDecoration-A decorative Figure intended to be placed on a Polyline. *extends PolygonDecoration  */ public class CircleDecoration extends Ellipse implements RotatableDecoration{private int myRadius = 5;/**中心点*/private Point myCenter = new Point();public void setRadius(int radius) {erase();myRadius = Math.abs(radius);bounds = null;repaint();}public void setLineWidth(int width) {super.setLineWidth(width);}public Rectangle getBounds() {if (bounds == null) {int diameter = myRadius * 2;bounds = new Rectangle(myCenter.x - myRadius,myCenter.y - myRadius, diameter, diameter);bounds.expand(lineWidth / 2, lineWidth / 2);}return bounds;}public void setLocation(Point p) {if (myCenter.equals(p)) {return;}myCenter.setLocation(p);bounds = null;}public void setReferencePoint(Point p) {// ignore, does not make sense to rotate circle}/*@Overrideprotected void fillShape(Graphics g) {g.drawOval(new Rectangle(1, 1, 20, 20));}*/}


有多个锚点,固定一个锚点。
有ToppicEditPart中添加代码:
private ConnectionAnchor sourceAnchor;@Overridepublic ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart connEditPart) {if (sourceAnchor == null) {sourceAnchor = new SourceFixedConnectionAnchor(getNodeFigure());}return sourceAnchor;}public class SourceFixedConnectionAnchor extends AbstractConnectionAnchor {public SourceFixedConnectionAnchor(IFigure owner) {super(owner);}public Point getLocation(Point reference) {Point right = getOwner().getBounds().getRight();Point p = new PrecisionPoint(right.x + 1, right.y - 1);getOwner().translateToAbsolute(p);return p;}}


在Topic2EditPart类中加入相同代码:




首选项设定
注意initDefaults方法是默认会调用的,你所需要的改变 只需要在这里修改即可。
private static RGB LINE_COLOR=new RGB(90,140,255);public static void initDefaults(IPreferenceStore store){AppearancePreferencePage.initDefaults(store);PreferenceConverter.setDefault(store,IPreferenceConstants.PREF_LINE_COLOR , LINE_COLOR);}


树型界面设计



监听机制实现
注意在任何一个EditPart中,都存在一个函数handleNotificationEvent,这个函数在模型的属性改变时会触发,在这里面我们监听priority
/**属性事件监听*/@Overrideprotected void handleNotificationEvent(Notification notification) {/** 事件类型 */int type = notification.getEventType();/** 事件产生对象 */if(notification.getNotifier() instanceof Topic){ if (notification.getFeature() instanceof EAttribute) {                 String attrName = ((EAttribute) notification.getFeature()).getName();                 if(attrName.equals("priority"))                 {                                  /**处理*/                TopicFigure f= (TopicFigure)(this.getFigure().getChildren().get(0));                                Topic obj=(Topic)((org.eclipse.gmf.runtime.notation.View)this.getModel()).getElement();                WrappingLabel la=(WrappingLabel) f.getChildren().get(0);                if(obj.getPriority()==Priority.HIGH)                {                }else                {                }                                 } }}super.handleNotificationEvent(notification);}
最终