`
mjtfly
  • 浏览: 51834 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

eclipse GMF 制作简单工作流流程设计器(3)

阅读更多
本节教程在第二节的基础上继续完善工作流流程设计器,本节的主要内容有:
  1. 自定义节点图标
  2. 自定义形状

1.自定义节点图标


通过GMF向导生成的节点都是矩形,为了使图形更加美观、更好的用户UI,我们需要自定义图形节点。下面以开始和结束活的为例,介绍如何使用自定义图标。


  1. 我们继续在第二节基础上,打开com.mjt.flow.diagram项目,在icons新建文件夹custom,将之前准备好的的图标放入该目录,这里使用的是start.png和end.png,图片大小32*32。
  2. 由于需要使用自定义图标,所以需要在flow.gmfgraph文件进行图形设置,需要将形状设置成自定义形状。

a) 选择Canvas Gallery Default->Figure Descriptor StartActivityFigure,将子节点Retangle StartActivityFigure删除,右键点击Figure Descriptor StartActivityFigure,New Child->Custom Figure, 输入名称StartActivityFigure, 在Qualified Class Name填写自定义的类名,这个类一般继承org.eclipse.draw2d.Figure,在这里填写类 名:com.mjt.flow.diagram.figure.StartActivityFigure,按照同样方法,在 EndActivityFigure新建Custom Figure;建立完毕后如下图:



b)开始和结束活动使用图片大小固定,在这里我们把它改成不可变大小,设置Node StartActivity和Node EndActivity的Resize Constraint为NONE,如下图:


 



c)在图形文件flow.gmfgraph定义了自定义类,现在需要建立这个两个类,首先新建开始活动Figure类,该类继承org.eclipse.draw2d.Figure这个类,如下:


 


d)类向导建立com.mjt.flow.diagram.figure.StartActivityFigure这个类后,这个类是个空白的类,什么都没有,现在我们覆盖基类的paintFigure(Graphics graphics)方法,输入以下代码:
package com.mjt.flow.diagram.figure;

import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.Graphics;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.graphics.Image;

import com.mjt.flow.diagram.part.FlowDiagramEditorPlugin;

public class StartActivityFigure extends Figure {
    
    @Override
    protected void paintFigure(Graphics graphics) {
        setFigureImage(graphics, "icons/custom/start.png",32,3); //$NON-NLS-1$
    }
    
    protected void setFigureImage(Graphics graphics, String imagePath, int width, int height){
        super.paintFigure(graphics);
        ImageDescriptor descriptor = FlowDiagramEditorPlugin.findImageDescriptor(imagePath);
        Image image = descriptor.createImage();//创建图形
        graphics.drawImage(image, getLocation());//绘制图标
        setPreferredSize(width, height); //设置首选(默认)大小
    }
}
按 照同样的方法,建立EndActivityFigure。两个类代码重复,可以将活动的Figure建立一个抽象类,如上述的 setFigureImage方法可以放到这个抽象类中,提高代码的重用性,在此处只是一个演示,建立两个相似的类,不进行优化了,有兴趣的话可以查看源 代码。

e)同时还需要设设置NodeFigure的DefaultSize,打开 com.mjt.flow.diagram.edit.parts.StartActivityEditPart这个类,在 createNodePlate()方法中新建DefaultSizeNodeFigure类时,需要设置DefaultSize为26、26,同时不要 忘记设置EndtActivityEditPart类,如下:
   /**
     * @generated NOT
     */
    protected NodeFigure createNodePlate() {
        DefaultSizeNodeFigure result = new DefaultSizeNodeFigure(26,26);
        return result;
    }
Tip:@generated NOT标注可以当GMF重新生成代码的时候不会被覆盖,不会重新生成。


f)gmfgrap文件改动过了,需要重新生成flow.gmfgen文件,删除flow.gmfgen文件,右键点击 flow.gmfmap文件,Create Generator Model...,点击Generate Diagram Code...,重新生成diagram code。

g)运行一下如下图:


 


h)细心的您是否发现,当在画开始和结束活动时,如果拖动的比较大时,此时图形有不能调整大小,怎么办呢?这时需要您添加另外的代码控制图形大小。
此 时需要覆盖com.mjt.flow.diagram.edit.parts.StartActivityEditPart中的 handleNotificationEvent(Notification notification)方法,在这里进行控制图形的大小,如下:
   /**
     * 创建图形时自动适应PreferredSize大小。
     * @generated NOT
     */
    @Override
    protected void handleNotificationEvent(Notification notification) {
        setToPreferredSize(notification, getFigure(),
                (View) getModel(), getEditingDomain(), getDiagramEditDomain());
        super.handleNotificationEvent(notification);
    }

    /**
     * Resize Constraint属性值改为NONE时,创建图形拖动时大小如果大于PreferredSize时,
     * 不会将图形适合到PreferredSize大小, 此方法为了解决这个问题
     * @generated NOT
     */
    public static void setToPreferredSize(Notification notification, IFigure figure, View model,
            TransactionalEditingDomain editingDomain, IDiagramEditDomain diagramEditDomain){
        if(notification.getEventType()==Notification.SET
                && !figure.getSize().equals(figure.getPreferredSize())){
            SetBoundsCommand boundsCommand = new SetBoundsCommand(editingDomain,"", //$NON-NLS-1$
                    new EObjectAdapter(model),figure.getPreferredSize());
            diagramEditDomain.getDiagramCommandStack().execute(new ICommandProxy(boundsCommand));
        }
    }

i)再仔细看一下下面的图形,有没有发现,当连接线成斜线的时候,由于里面的图形是圆形而外框是矩形,默认情况下,连接线的锚点是矩形的。如下:


 


如 何自定义锚点呢?这时候需要覆盖 com.supcon.workflow.xpdl.diagram.edit.parts.StartActivityEditPart#getSourceConnectionAnchor 和#getTargetConnectionAnchor方法,如下:
    /**
     * @generated NOT
     */
    @Override
    public ConnectionAnchor getSourceConnectionAnchor(
            ConnectionEditPart connEditPart) {
        return new EllipseAnchor(getFigure());
    }

    /**
     * @generated NOT
     */
    @Override
    public ConnectionAnchor getSourceConnectionAnchor(Request request) {
        return new EllipseAnchor(getFigure());
    }

    /**
     * @generated NOT
     */
    @Override
    public ConnectionAnchor getTargetConnectionAnchor(
            ConnectionEditPart connEditPart) {
        return new EllipseAnchor(getFigure());
    }

    /**
     * @generated NOT
     */
    @Override
    public ConnectionAnchor getTargetConnectionAnchor(Request request) {
        return new EllipseAnchor(getFigure());
    }

draw2d 为我们提供很多默认的Anchor,这里使用的是椭圆的Anchor,实现的Anchor除了EllipseAnchor还有 DiamondConnectionAnchor、ChopboxAnchor、SlidableAnchor等,有兴趣的话可以自己去研究一下,同时可 以自定义Anchor,只要继承抽象类org.eclipse.draw2d.AbstractConnectionAnchor来完成自定义的 ConnectionAnchor。

再看一下运行结果:


 



2.自定义形状

这一块内容我们将以AutoActivity活动为例,对其进行自定义形状,采用渐变填充。

a)首先按照自定义节点图标的方法,在flow.gmfgraph新建Custom Figure, 由于原来有子节点GridLayout和Label, 删除后重新加上去,如下图:


 


b) 新建自定义形状类com.mjt.flow.diagram.figure.AutoActivityFigure, 继承org.eclipse.draw2d.Shape,由于Shape是抽象类,需要实现两个方法fillShape(Graphics graphics)和outlineShape(Graphics graphics),前面主要用于图形填充,后者用于形状外边框。
类代码如下:
package com.mjt.flow.diagram.figure;

import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.Shape;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Path;
import org.eclipse.swt.graphics.RGB;

/**
 * 自动活动自定义Figure
 */
public class AutoActivityFigure extends Shape {

    protected Dimension corner = new Dimension(20, 20);

    @Override
    protected void fillShape(Graphics graphics) {
        //通过路径绘制圆角矩形
        Path path = new Path(null);
        path.addArc(getBounds().x, getBounds().y, corner.width, corner.height, 180, -90);
        path.addArc(getBounds().x+getBounds().width-corner.width, getBounds().y, corner.width, corner.height, 90,-90);
        path.addArc(getBounds().x+getBounds().width-corner.width, getBounds().y+getBounds().height-corner.height, corner.width, corner.height, 0,-90);
        path.addArc(getBounds().x, getBounds().y+getBounds().height-corner.height, corner.width, corner.height, 270,-90);
        graphics.setClip(path);
        
        //渐变填充
        graphics.setForegroundColor(ColorConstants.white);
        graphics.setBackgroundColor(new Color(null, new RGB(200,220,230)));
        graphics.fillGradient(getBounds(), true);
    }

    @Override
    protected void outlineShape(Graphics graphics) {
        float lineInset = Math.max(1.0f, getLineWidthFloat()) / 2.0f;
        int inset1 = (int) Math.floor(lineInset);
        int inset2 = (int) Math.ceil(lineInset);

        Rectangle r = Rectangle.SINGLETON.setBounds(getBounds());
        r.x += inset1;
        r.y += inset1;
        r.width -= inset1 + inset2;
        r.height -= inset1 + inset2;

        graphics.setForegroundColor(new Color(null, new RGB(40,100,120)));
        graphics.drawRoundRectangle(r, Math.max(0, corner.width
                - (int) lineInset), Math
                .max(0, corner.height - (int) lineInset));
    }

}
上面定义的圆角椭圆半径为(20,20)。

c)重新生成flow.gmfgen文件,并重新生成diagram代码。

d)运行结果如下:


 

源代码请看附件


这一节讲完了,下一节的内容是如何扩展流程的自定义字段。



 

 

由于平时比较忙,可能写的比较简单,有些地方没有详细说明,一笔带过,如果有什么不明白之处,欢迎通过邮件联系。

本系列教程尽量会在最短的时间内写出来。

 

 


  • 大小: 149.5 KB
  • 大小: 76.4 KB
  • 大小: 143.9 KB
  • 大小: 69.5 KB
  • 大小: 9.3 KB
  • 大小: 9.1 KB
  • 大小: 148.2 KB
  • 大小: 88.3 KB
6
0
分享到:
评论
4 楼 cutesunshineriver 2011-09-01  
sorry,弄错了,你是想在把图形选定范围拖大后再拖回的时候设置回默认的size,你的代码是对的。

不过放大之后图形不能跟着放大,始终是有点怪怪的。
3 楼 cutesunshineriver 2011-09-01  
/**
     * 创建图形时自动适应PreferredSize大小。
     * @generated NOT
     */
    @Override
    protected void handleNotificationEvent(Notification notification) {
        setToPreferredSize(notification, getFigure(),
                (View) getModel(), getEditingDomain(), getDiagramEditDomain());
        super.handleNotificationEvent(notification);
    }

    /**
     * Resize Constraint属性值改为NONE时,创建图形拖动时大小如果大于PreferredSize时,
     * 不会将图形适合到PreferredSize大小, 此方法为了解决这个问题
     * @generated NOT
     */
    public static void setToPreferredSize(Notification notification, IFigure figure, View model,
            TransactionalEditingDomain editingDomain, IDiagramEditDomain diagramEditDomain){
        if(notification.getEventType()==Notification.SET
                && !figure.getSize().equals(figure.getPreferredSize())){
            SetBoundsCommand boundsCommand = new SetBoundsCommand(editingDomain,"", //$NON-NLS-1$
                    new EObjectAdapter(model),figure.getPreferredSize());
            diagramEditDomain.getDiagramCommandStack().execute(new ICommandProxy(boundsCommand));
        }
    }

---------------------------------------------------------------------
加上这段代码,resize开始活动也不会放大图形。(GMF1.4、GEF3.6)
2 楼 mjtfly 2009-07-19  
1。首先可以学习官方的教程:http://wiki.eclipse.org/index.php/GMF_Tutorial

2。可以去研究现存产品的GMF应用,可以去研究eclipse STPBPMN (BPMN)的源代码,其应用的地址如下:http://www.eclipse.org/bpmn/

3。学习其他成熟产品的源代码,像这类开源的产品很多的,比如UML设计器等等。
1 楼 zhoujg 2009-07-18  
不错,按照你的步骤就知道怎么建立一个模型了。
问一下,具体的学习资料有哪些可以参考呢?

相关推荐

    Eclipse 3高级编程

    2. **工作流和工作空间**:Eclipse的工作空间是项目管理的基础,了解如何有效地组织和管理工作空间中的项目,以及如何设置工作流以提高开发效率,如版本控制集成、构建过程自动化等。 3. **JDT(Java Development ...

    eclipse插件集合

    9. **图形设计**:如GMF或BPMN,用于绘制UML图或业务流程图。 安装Eclipse插件通常可以通过Eclipse的内置市场(Eclipse Marketplace)进行,也可以通过下载插件的`.jar`文件,然后通过Eclipse的“Install New ...

    Activiti Designer5.15.0源码

    Activiti Designer是一款基于Eclipse的流程建模工具,它提供了图形化的用户界面,使得开发者能够方便地设计和管理业务流程。Activiti Designer是Activiti工作流引擎的一部分,它基于BPMN 2.0标准,使得流程定义符合...

    eclipse插件大全

    10. **设计和图形化** -比如GMF(Generated Model Framework)和BPEL Designer,用于创建图形化的工作流和数据模型。 11. **数据库工具** - DBeaver或MyEclipse Database Explorer允许开发者直接在Eclipse中连接、...

    Eclipse常用插件

    4. **项目构建与自动化插件**:Maven和Gradle是两种流行的构建工具,M2E(Maven Integration for Eclipse)和Gradle IDE插件帮助开发者在Eclipse中无缝管理依赖和构建流程。 5. **测试与调试插件**:JUnit是Java...

    emf-runtime-2.9.2.zip

    标签"java eclipse"表明这个插件是为Eclipse IDE的Java开发环境设计的,意味着它可以很好地集成到Java开发工作流中,为Java项目提供模型驱动的开发能力。 总的来说,"emf-runtime-2.9.2.zip"是一个用于增强Eclipse ...

    rcp工程的描述

    这些功能定义了应用程序的核心功能或特定的工作流。例如,你可以创建一个名为"MyAppFeature"的功能,该功能可能包含处理用户界面、数据库连接、业务逻辑等多个插件。通过这种方式,你可以清晰地组织和管理应用程序的...

    Asynchronous-Stream-Processing-Applications-DSL:用于设计和实现异步流处理应用程序的领域特定语言(DSL)

    在这种情况下,DSL的使用可能会涉及如GMF/Eugenia这样的图形编辑器,它们提供可视化工具帮助开发者设计流程图,然后自动生成相应的Java代码。 GMF(Graphics Modeling Framework)是Eclipse项目的一部分,它是一个...

    开源软件架构 软件架构

    其中,EMF(Eclipse Modeling Framework)、GEF(Graphical Editing Framework)和GMF(Graphical Modeling Framework)是Eclipse平台下的三个重要框架: - **EMF**:用于构建模型驱动的应用程序。 - **GEF**:用于...

    EMF To GraphViz-开源

    5. 命令行接口:对于自动化脚本或集成到其他工作流中,可能提供命令行工具。 使用EMF To GraphViz,开发者和模型设计师可以: 1. 快速查看模型结构,无需构建完整的GMF编辑器。 2. 分析模型的复杂性,发现潜在的...

    EMF代码生成Merge

    标题中的“EMF代码生成Merge”指的是使用 Eclipse Modeling Framework (EMF) 进行代码生成并合并的过程。EMF 是 Eclipse 开发平台的一部分,它提供了一种强大的方式来定义、创建、操作和共享数据模型,同时也支持从...

Global site tag (gtag.js) - Google Analytics