以文本方式查看主题

-  计算机科学论坛  (http://bbs.xml.org.cn/index.asp)
--  『 Java/Eclipse 』  (http://bbs.xml.org.cn/list.asp?boardid=41)
----  [转帖]GEF实践总结(二)常见基础性问题  (http://bbs.xml.org.cn/dispbbs.asp?boardid=41&rootid=&id=76631)


--  作者:hongjunli
--  发布时间:9/8/2009 12:18:00 PM

--  [转帖]GEF实践总结(二)常见基础性问题

关键字: gef总结 model editpart figure
一. 怎么通过model创建对应的EditPart?
EditPartFactory :通过model创建对应EditPart的工厂类。
就和jface.TableView一样,能知道通过model得到TableItem。和jface.TreeViewer一样,能通过model知道要生成对应的TreeItem一样的功效。

Java代码
@Override  
public EditPart createEditPart(EditPart context, Object model) {   
EditPart part = null;   
if (model instanceof DiagramModel) {   
part = new DiagramEditPart();   
} else if (model instanceof RectModel) {   
part = new RectEditPart();   
}   
part.setModel(model);   
return part;   
}  

@Override
public EditPart createEditPart(EditPart context, Object model) {
EditPart part = null;
if (model instanceof DiagramModel) {
part = new DiagramEditPart();
} else if (model instanceof RectModel) {
part = new RectEditPart();
}
part.setModel(model);
return part;
}


二. EditPart怎么创建对应的Figure?
在EditPart中有一个方法必须实现,就是createFigure方法。

Java代码
@Override  
protected IFigure createFigure() {   
RectFigure figure = new RectFigure();   
figure.setModel((BaseModel) this.getModel());   
return figure;   
}  

@Override
protected IFigure createFigure() {
RectFigure figure = new RectFigure();
figure.setModel((BaseModel) this.getModel());
return figure;
}


这样就把EditPart和对应的Figure关联起来了,知道如何通过EditPart创建出一个对应的Figure。

三. Model改变,如果对外通知?
Model中有PropertyChangeSupport,外部可以往model中注册PropertyChangeListener,也就是对模型属性改变的监听器,如果model的属性发生了改变,那么就会对所有的listener通知这个属性变化。通知内容包括改变的属性名称、老的值、新的值。

Java代码
protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {   
changeSupport.firePropertyChange(propertyName, oldValue, newValue);   
}   
public void setX(int x) {   
int oldX = this.x;   
this.x = x;   
this.firePropertyChange(“X”, oldX, x);   
}  

protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
changeSupport.firePropertyChange(propertyName, oldValue, newValue);
}
public void setX(int x) {
int oldX = this.x;
this.x = x;
this.firePropertyChange(“X”, oldX, x);
}

比如:上面的代码,当属性x发生变化的时候就对外通知”X”发生了变化,值从oldX变成了x。

四. EditPart是何时将自己注册到model的呢?
EditPart都是实现了PropertyChangeListener接口,表示:自身就是一个属性变化的监听器,可以对被监听者(比如model)的属性改变进行监听。见下面的代码:

Java代码
/**  
* @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#activate()  
*/  
public void activate() {   
if (!isActive()) {   
super.activate();   
((BaseModel) getModel()).addPropertyChangeListener(this);   
}   
}   
  
/**  
* @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#deactivate()  
*/  
public void deactivate() {   
if (isActive()) {   
super.deactivate();   
((BaseModel) getModel()).removePropertyChangeListener(this);   
}   
}  

/**
* @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#activate()
*/
public void activate() {
if (!isActive()) {
super.activate();
((BaseModel) getModel()).addPropertyChangeListener(this);
}
}

/**
* @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#deactivate()
*/
public void deactivate() {
if (isActive()) {
super.deactivate();
((BaseModel) getModel()).removePropertyChangeListener(this);
}
}

在EditPart被激活的时候(activate),就已经将自己作为监听器放入了model中了,在EditPart被销毁的时候(deactivate)的时候去掉的model的监听。

五. EditPart得知属性改变后做了什么事情?

Java代码
/**  
* @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)  
*/  
@Override  
public void propertyChange(PropertyChangeEvent evt) {   
String property = evt.getPropertyName();   
  
if (IPropertyConst.CHILDREN.equals(property)) {   
refreshChildren();   
} else {   
refreshVisuals();   
}   
}  

/**
* @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
*/
@Override
public void propertyChange(PropertyChangeEvent evt) {
String property = evt.getPropertyName();

if (IPropertyConst.CHILDREN.equals(property)) {
refreshChildren();
} else {
refreshVisuals();
}
}

上面的这段代码,说明了,当被监听者(model)的属性改变的时候,EditPart得知属性改变后做了什么事情。如果是添加或删除了孩子模型(Children),那么就是刷新所有小孩,重新绘制他们。其他的属性改变的时候,就把自己刷新一下(当然refreshVisuals中还有更多的逻辑)。

六. Model如何告诉Figure具体绘图的位置?

Java代码
/**  
* @see org.eclipse.gef.editparts.AbstractEditPart#refreshVisuals()  
*/  
protected void refreshVisuals() {   
BaseModel model = (BaseModel) getModel();   
Rectangle bounds = new Rectangle(model.getX(), model.getY(), model.getW(), model.getY());   
((GraphicalEditPart) getParent()).setLayoutConstraint(this, getFigure(), bounds);   
}  

/**
* @see org.eclipse.gef.editparts.AbstractEditPart#refreshVisuals()
*/
protected void refreshVisuals() {
BaseModel model = (BaseModel) getModel();
Rectangle bounds = new Rectangle(model.getX(), model.getY(), model.getW(), model.getY());
((GraphicalEditPart) getParent()).setLayoutConstraint(this, getFigure(), bounds);
}
  
上面的代码在EditPart中,当属性改变时候,就告诉父EditPart,重新调整当前的位置,当然,新的位置信息来自于model。
注意:上面这段代码用于XYLayout的情况下,如果是GridLayout,需要传递GridData对象。其他的Layout也会有其他不同的参数传递和处理。


七. Model如果是父子结构的,EditPart如何知道呢?

Java代码
/**  
* @see org.eclipse.gef.editparts.AbstractEditPart#getModelChildren()  
*/  
protected List<BaseModel> getModelChildren() {   
return ((BaseContainerModel) this.getModel()).getChilds();   
}  

/**
* @see org.eclipse.gef.editparts.AbstractEditPart#getModelChildren()
*/
protected List<BaseModel> getModelChildren() {
return ((BaseContainerModel) this.getModel()).getChilds();
}

就在于上面的代码,如果model有小孩,就将所有的model的小孩返回,那么EditPart就能知道当前的model是否是父子架构的了。

八. 总结
通过上面的内容已经能够明白:model->EditPart->Figure 的属性变化的传递和如何响应。这其实是GEF中模型变化影响UI界面的一条途径。
还有另一条途径就是通过界面操作,产生Request,通过EditPart的EditPolicy生成Command,Command改变model,从而影响界面。这第二条路以后会提到。

原文地址:http://lggege.javaeye.com/blog/463724


W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
8,109.375ms