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)运行结果如下:


 

源代码请看附件


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



 

 

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

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

 

 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值