`
sunway
  • 浏览: 115155 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

第四章 GEF框架(1)

阅读更多
From:http://www.blog.edu.cn/user1/19180/archives/2005/375044.shtml

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接口,这表明它可以被附着。
分享到:
评论

相关推荐

    第四章 GEF框架.doc

    第四章 GEF框架详解 GEF(Graphical Editing Framework)是一个基于Draw2D的Eclipse插件,主要用于构建图形编辑工具。它不仅提供了图形界面的基本处理机制,还通过监听和响应用户交互事件(如鼠标、键盘和Workbench...

    [翻译]Eclipse图形化编辑框架(GEF)/更新第7章:层和视图

    这有助于开发者在实际开发中更好地利用GEF框架。 **总结** Eclipse图形化编辑框架(GEF)通过层和视图的机制,提供了强大的图形编辑工具构建能力。层的管理使得元素的绘制和交互更加灵活,而视图则提供了展示模型...

    GEF中文教程+代码

    总的来说,这个“GEF中文教程+代码”资源是学习和掌握GEF框架的理想材料。通过系统地学习和实践,开发者可以快速地掌握图形编辑器的开发技术,从而构建出自己的图形化应用。无论你是初学者还是有经验的开发者,这个...

    GEF入门学习例子

    4. **移动、删除、撤销/重做**: 这些基本操作通过GEF的命令框架实现。例如,移动操作对应于一个移动命令,删除操作对应于删除命令,这些命令都可以被添加到`CommandStack`中,支持撤销和重做。 5. **大纲视图**: ...

    eclipse图形建模框架(gef)

    ### Eclipse 图形建模框架(GEF):新手开发指南 #### 一、概述 Eclipse Graphical Editing Framework(简称 GEF)是 Eclipse 平台提供的一个强大的图形编辑框架,它能够帮助开发者快速构建出复杂且功能丰富的图形...

    gef版本的helloworld

    从给定文件的内容来看,该文档提供了一个关于如何在GEF框架下创建一个简单的HelloWorld应用程序的教程。这个教程特别适合初学者,同时也适合作为一本工具书使用。教程详细地介绍了RCP工程的建立、GEF在Eclipse环境中...

    gef eclipse org

    标题“gef eclipse org”指的是在Eclipse集成开发环境中安装用于Android开发的GEF(图形化编辑框架)插件的过程。GEF(Graphical Editing Framework)是Eclipse平台的一部分,主要用于构建图形化的用户界面和应用程序...

    【java必备】GEF-SDK-3.1.1.zip

    1. **库文件**:包含GEF的核心库,如`gef.jar`,以及可能依赖的Eclipse库,如`org.eclipse.core.runtime`、`org.eclipse.draw2d`和`org.eclipse.gef`等。这些库文件使得开发者能够调用GEF提供的API来创建图形元素、...

    gef-step2.rar_GEF eclipse_gef

    **GEF(Graphical Editing Framework)图形编辑框架**是Eclipse平台下的一个重要组成部分,它为开发者提供了一套全面的工具和API,用于构建强大的图形用户界面(GUI)应用程序,特别是那些涉及图形化建模和编辑的...

    GEF-whole-upload.rar_gef_whole

    **GEF(Graphical Editing Framework)** 是一个用于构建图形编辑框架的开源项目,由Eclipse基金会维护。这个框架提供了一套完整的工具和接口,帮助开发者创建基于模型的图形用户界面,尤其适用于开发复杂的可视化...

    eclipse-jsp插件-GEF-ALL-3.10.0

    1. **GEF(Graphical Editing Framework)**:这是一个开放源代码的框架,主要用于构建图形用户界面,特别是那些需要进行图形编辑的应用程序。GEF为开发者提供了构建图形编辑器的基础结构,包括模型-视图-控制器...

    gef官方英文教程

    1. **入门指南**:介绍如何设置Eclipse环境,导入GEF项目,并创建第一个简单的图形编辑器。 2. **模型与视图**:讲解如何定义和使用模型,以及如何将模型数据映射到视图元素上。 3. **图元工厂(GEF Metafactories)...

    GEF进阶 IBM社区文档整理

    - **其他资源**:了解更多的GEF教程和技术文档,可以帮助开发者更好地理解和运用GEF框架的各种特性。 #### 七、相关链接 - **Opensource技术文档库**:提供更多关于开源项目的文档资料。 - **developerWorks中国**...

    GEF-runtime-3.1

    标题 "GEF-runtime-3.1" 指的是 Generalized Eclipse Framework 运行时环境的第三版。GEF(Generalized Editing Framework)是Eclipse IDE中的一个核心组件,主要用于构建图形化编辑器和可视化工具。它为开发人员...

    gef源码文件

    这个压缩包包含了gef、ui和darw2d三个部分的源码,我们将逐一探讨它们在Gef框架中的作用和相关知识点。 首先,`gef`是核心模块,它提供了丰富的命令集,用于增强GDB的功能。通过这些命令,开发者可以方便地进行内存...

    GEF中文教程(以hello world为例)

    ### GEF中文教程知识点概述 ...- 对于初学者来说,理解GEF的基本概念以及如何搭建其基础结构是非常重要的第一步。随着实践经验的积累,将能够更加熟练地运用GEF开发出功能丰富且界面友好的图形编辑器应用。

    eclipse插件开发学习笔记(扫描版15-28章)

    9. **第20章 GEF介绍与实现**:GEF(Graphical Editing Framework)是Eclipse中的图形编辑框架,用于创建图形化编辑器。本章可能涉及了GEF的基本概念,以及如何利用它来构建可视化的编程或设计工具。 10. **第22章 ...

    eclipse rcp 插件开发学习笔记.pdf 15-24章

    1. **第15章:对话框和向导(Dialogs and Wizards)** - 在Eclipse RCP中,对话框和向导是用户交互的重要组成部分。对话框用于获取用户的输入或显示信息,而向导则引导用户完成一系列步骤。本章可能涵盖了如何创建...

    Eclipse插件开发学习笔记22-24章.rar

    首先,第22章“GEF介绍与实现”详细讲解了GEF框架的基本概念。GEF是Eclipse中用于创建图形编辑器的框架,它提供了一套完整的机制,用于构建基于图形界面的开发工具。本章可能涉及以下知识点: 1. GEF的基本架构:...

    Eclipse插件开发 part2

    第22章的“Eclipse插件开发学习笔记 第三篇高级进阶 第四篇综合实例 目录.pdf”可能是一个学习指南,列出了更深入的高级主题和综合实例的目录,帮助读者按部就班地学习和实践。 最后,“《Eclipse插件开发学习笔记...

Global site tag (gtag.js) - Google Analytics