第四章 GEF框架(1)

[b]From:http://www.blog.edu.cn/user1/19180/archives/2005/375044.shtml[/b]

[size=medium]4.1 概述

GEF是一套建立在Draw2D基础之上的eclipse插件,它为Draw2D提供控制功能,它监听各种事件,如鼠标、键盘、Workbench的事件,并进行响应。GEF是一套框架,它提供一套完整的图形用户接口系统的基本处理方式,但是具体的功能需要我们实现,这一点和MFC的窗口系统不同。

GEF使用MVC模式,它成功的将模型、视图、控制器三个部分剥离。模型是由用户编写的任何类,视图则采用Draw2D系统,控制器则是之前提到过的EditPart。

M-V-C三个部分的交互式这样完成的:当用户直接对V进行了操作,比如改变V的形状或者修改了Label中的文字,系统就会产生一个Request,并将这个Request传递给相应的EditPart进行处理;EditPart根据Request的类型生成相应的Command(Command需要用户编写),并将Command在传递出去;系统得到Command后,就会在合适的时机执行这个Command。如果M发生了变化,并且需要更新视图,它可以使用一个PropertyChangeSupport实例,提示EditPart对V进行改变。PropertyChangeSupport实际上是M与EditPart的一个桥梁,只要在EditPart中实现PropertyChangeListener接口,就可以向M的PropertyChangeSupport实例注册自己为监听者。具体的例子将在第3节给出。

实现一个模型是很简单,但是注意一般来说应该让模型包含一个PropertyChangeSupport类的实例。调用PropertyChangeSupport的addPropertyChangeListener方法可以向其中注册一个监听者,调用removePropertyChangeListener的移出一个监听者,调用firePropertyChange方法则向所有注册的监听者通知发生了变化。

实现一个EditPart一般来说需要重载performRequest、getCommand、activate、deactivate和refreshVisuals函数,并实现createEditPolicies、createFigure接口函数,为了让EditPart能够成为PropertyChangeListener,你还必须实现PropertyChangeListener接口。performRequest和getCommand将在第3节介绍,activate和deactivate用于处理当EditPart处于激活或者非激活状态时的操作,一般来说,可以在这两个函数中注册和移除自己监听者的角色。refreshVisuals函数用于更新自己的视图。

下面给出一个模型和它对应的EditPart的例子:
Element.java:

package com.example.model;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;

public abstract class Element implements Cloneable, Serializable {

PropertyChangeSupport listeners = new PropertyChangeSupport(this);

public void addPropertyChangeListener(PropertyChangeListener l) {
listeners.addPropertyChangeListener(l);
}

protected void firePropertyChange(String prop, Object old, Object newValue) {
listeners.firePropertyChange(prop, old, newValue);
}

protected void fireStructureChange(String prop, Object child) {
listeners.firePropertyChange(prop, null, child);
}

public void removePropertyChangeListener(PropertyChangeListener l) {
listeners.removePropertyChangeListener(l);
}

}


注意这个Element类中包含了一个PropertyChangeSupport对象。

Node.java:

package com.example.model;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.ui.views.properties.ComboBoxPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;
import org.eclipse.ui.views.properties.TextPropertyDescriptor;

public class Node extends Element implements IPropertySource {
final public static String PROP_LOCATION = "LOCATION";

final public static String PROP_NAME = "NAME";

final public static String PROP_VISIBLE = "VISIBLE";

final public static String PROP_INPUTS = "INPUTS";

final public static String PROP_OUTPUTS = "OUTPUTS";

protected Point location = new Point(0, 0);

private Dimension size=new Dimension(150,40);

protected String name = "Node";

protected boolean visible = true;

protected IPropertyDescriptor[] descriptors = new IPropertyDescriptor[] {
new TextPropertyDescriptor(PROP_NAME, "Name"),
new ComboBoxPropertyDescriptor(PROP_VISIBLE, "Visible", new String[] { "true", "false" }) };

protected List outputs = new ArrayList(5);

protected List inputs = new ArrayList(5);

public void addInput(Connection connection) {
this.inputs.add(connection);
fireStructureChange(PROP_INPUTS, connection);
}

public void addOutput(Connection connection) {
this.outputs.add(connection);
fireStructureChange(PROP_OUTPUTS, connection);
}

public List getIncomingConnections() {
return this.inputs;
}

public List getOutgoingConnections() {
return this.outputs;
}

public void removeInput(Connection connection) {
this.inputs.remove(connection);
fireStructureChange(PROP_INPUTS, connection);
}

public void removeOutput(Connection connection) {
this.outputs.remove(connection);
fireStructureChange(PROP_OUTPUTS, connection);
}

public boolean isVisible() {
return visible;
}

public void setVisible(boolean visible) {
if (this.visible == visible) {
return;
}
this.visible = visible;
firePropertyChange(PROP_VISIBLE, null, Boolean.valueOf(visible));
}

public String getName() {
return name;
}

public void setName(String name) {
if (this.name.equals(name)) {
return;
}
this.name = name;
firePropertyChange(PROP_NAME, null, name);
}

public void setLocation(Point p) {
if (this.location.equals(p)) {
return;
}
this.location = p;
firePropertyChange(PROP_LOCATION, null, p);
}

public Point getLocation() {
return location;
}

public void setSize(Dimension size) {
this.size = size;
}

public Dimension getSize() {
return size;
}

//------------------------------------------------------------------------
// Abstract methods from IPropertySource

public Object getEditableValue() {
return this;
}

public IPropertyDescriptor[] getPropertyDescriptors() {
return descriptors;
}

public Object getPropertyValue(Object id) {
if (PROP_NAME.equals(id))
return getName();
if (PROP_VISIBLE.equals(id))
return isVisible() ? new Integer(0) : new Integer(1);
return null;
}

public boolean isPropertySet(Object id) {
return true;
}

public void resetPropertyValue(Object id) {

}

public void setPropertyValue(Object id, Object value) {
if (PROP_NAME.equals(id))
setName((String) value);
if (PROP_VISIBLE.equals(id))
setVisible(((Integer) value).intValue() == 0);
}

}

这个Node继承自Element,并且实现了IPropertySource,这表明它可以作为属性页的数据源。下面再看对应的EditPart:
NodePart.java:

package com.example.parts;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;

import org.eclipse.draw2d.ChopboxAnchor;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.NodeEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.gef.requests.DirectEditRequest;
import org.eclipse.gef.tools.DirectEditManager;
import org.eclipse.jface.viewers.TextCellEditor;

import com.example.commands.RenameNodeCommand;
import com.example.commands.ResizeNodeCommand;
import com.example.figures.NodeFigure;
import com.example.model.Node;
import com.example.policies.NodeDirectEditPolicy;
import com.example.policies.NodeEditPolicy;
import com.example.policies.NodeGraphicalNodeEditPolicy;

public class NodePart extends AbstractGraphicalEditPart implements PropertyChangeListener, NodeEditPart {

protected DirectEditManager manager;

public void performRequest(Request req) {
if (req.getType().equals(RequestConstants.REQ_DIRECT_EDIT)) {
if (manager == null) {
NodeFigure figure = (NodeFigure) getFigure();
manager = new NodeDirectEditManager(this, TextCellEditor.class, new NodeCellEditorLocator(figure));
}
manager.show();
}
}
public Command getCommand(Request request) {
if(REQ_RESIZE.equals(request.getType())) {
ChangeBoundsRequest req=(ChangeBoundsRequest)request;
Node node=(Node)getModel();
ResizeNodeCommand cmd=new ResizeNodeCommand(node,this);
Rectangle rect=new Rectangle(node.getLocation(),node.getSize());
cmd.setRectangle(req.getTransformedRectangle(rect));
return cmd;
}
return super.getCommand(request);
}

public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(Node.PROP_LOCATION))
refreshVisuals();
else if (evt.getPropertyName().equals(Node.PROP_NAME))
refreshVisuals();
else if (evt.getPropertyName().equals(Node.PROP_INPUTS))
refreshTargetConnections();
else if (evt.getPropertyName().equals(Node.PROP_OUTPUTS))
refreshSourceConnections();
}

protected IFigure createFigure() {
return new NodeFigure();
}

protected void createEditPolicies() {
installEditPolicy(EditPolicy.DIRECT_EDIT_ROLE, new NodeDirectEditPolicy());
installEditPolicy(EditPolicy.COMPONENT_ROLE, new NodeEditPolicy());
installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE, new NodeGraphicalNodeEditPolicy());
}

public void activate() {
if (isActive()) {
return;
}
super.activate();
((Node) getModel()).addPropertyChangeListener(this);
}

public void deactivate() {
if (!isActive()) {
return;
}
super.deactivate();
((Node) getModel()).removePropertyChangeListener(this);
}

protected void refreshVisuals() {
Node node = (Node) getModel();
Point loc = node.getLocation();
Dimension size = node.getSize();
Rectangle rectangle = new Rectangle(loc, size);
((NodeFigure) this.getFigure()).setName(((Node) this.getModel()).getName());
//this.getFigure().setBounds(rectangle);
((GraphicalEditPart) getParent()).setLayoutConstraint(this, getFigure(), rectangle);
}

//------------------------------------------------------------------------
// Abstract methods from NodeEditPart

public ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart connection) {
return new ChopboxAnchor(getFigure());
}

public ConnectionAnchor getSourceConnectionAnchor(Request request) {
return new ChopboxAnchor(getFigure());
}

public ConnectionAnchor getTargetConnectionAnchor(ConnectionEditPart connection) {
return new ChopboxAnchor(getFigure());
}

public ConnectionAnchor getTargetConnectionAnchor(Request request) {
return new ChopboxAnchor(getFigure());
}

protected List getModelSourceConnections() {
return ((Node) this.getModel()).getOutgoingConnections();
}

protected List getModelTargetConnections() {
return ((Node) this.getModel()).getIncomingConnections();
}

}

这个EditPart还实现了NodeEditPart接口,这表明它可以被附着。[/size]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值