码迷,mamicode.com
首页 > 系统相关 > 详细

Eclipse GEF UMLClass(1)

时间:2016-05-12 18:03:40      阅读:313      评论:0      收藏:0      [点我收藏+]

标签:

通过两篇文章对GEF进行了介绍,为了自己加深对GEF的理解和学习,从网上找了一下开源的amaterasuml的uml工具,并把其中对内容转换提取成。

Figure:

第一篇文章其实是对amaterasuml中ClassFigure的简化,真实的UML类图如下:
技术分享

EntityFigure:实体Figure,用于获取Label和获取矩形编辑域,代码如下:

import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.geometry.Rectangle;


public interface EntityFigure extends IFigure{

    Label getLabel();

    Rectangle getCellEditorRectangle();

}

PresentaionFigure:描述Figure,用于更新模型的描述

public interface PresentationFigure {

    void updatePresentation(AbstractUMLModel model);
}

CompartmentFigure:用于分隔的Figure,用于分隔属性和方法

import org.eclipse.draw2d.AbstractBorder;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.ToolbarLayout;
import org.eclipse.draw2d.geometry.Insets;

public class CompartmentFigure extends Figure {

    public CompartmentFigure() {
        ToolbarLayout layout = new ToolbarLayout();
        layout.setMinorAlignment(ToolbarLayout.ALIGN_TOPLEFT);
        layout.setStretchMinorAxis(false);
        layout.setSpacing(2);
        setLayoutManager(layout);
        setBorder(new CompartmentFigureBorder());
    }

    public class CompartmentFigureBorder extends AbstractBorder {

        public Insets getInsets(IFigure figure) {
            return new Insets(1, 0, 2, 0);
        }

        public void paint(IFigure figure, Graphics graphics, Insets insets) {
            graphics.drawLine(getPaintRectangle(figure, insets).getTopLeft(),
                    tempRect.getTopRight());
        }
    }
}

UMLClassFigure:最终展示的Figure,主要的ClassFigure,包含所有相关方法

import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.ToolbarLayout;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;

public class UMLClassFigure extends Figure implements EntityFigure, PresentationFigure {



public static Color classColor = new Color(null, 255, 255, 206);

    private Label name;

    private Label stereoType;

    private Image icon;

    private CompartmentFigure attributeFigure = new CompartmentFigure();
    private CompartmentFigure methodFigure = new CompartmentFigure();
    private Figure nameFigure;

    public UMLClassFigure(Image icon, Figure nameFigure) {
        this.nameFigure = nameFigure;
        this.name = new Label();
        this.name.setForegroundColor(ColorConstants.darkGray);
        this.name.setBorder(new MarginBorder(5));
        this.name.setIcon(icon);
        this.icon = icon;
        this.stereoType = new Label();
        this.stereoType.setTextAlignment(PositionConstants.CENTER);
        ToolbarLayout layout = new ToolbarLayout();
        setLayoutManager(layout);
        setBorder(new LineBorder(1));
        setBackgroundColor(classColor);
        setOpaque(true);

        nameFigure.setLayoutManager(new ToolbarLayout());
//
//      nameFigure.add(this.stereoType);
        nameFigure.add(this.name);
        add(nameFigure);
        add(attributeFigure);
        add(methodFigure);
    }

    public void setFont(Font font){
        this.name.setFont(font);
    }

    public void setClassName(String className){
        this.name.setText(className);
    }

    public void add(IFigure figure, Object constraint, int index) {
        if(figure instanceof AttributeLabel){
            attributeFigure.add(figure);
        } else if(figure instanceof OperationLabel){
            methodFigure.add(figure);
        } else {
            super.add(figure,constraint,index);
        }
    }

    public void moveAttribute(int index, boolean up){
        @SuppressWarnings("rawtypes")
        List children = attributeFigure.getChildren();
        IFigure obj = (IFigure)children.get(index);
        attributeFigure.remove(obj);
        if(up){
            attributeFigure.add(obj, index - 1);
        } else {
            attributeFigure.add(obj, index + 1);
        }
    }

    public void moveOperation(int index, boolean up){
        @SuppressWarnings("rawtypes")
        List children = methodFigure.getChildren();
        IFigure obj = (IFigure)children.get(index);
        methodFigure.remove(obj);
        if(up){
            methodFigure.add(obj, index - 1);
        } else {
            methodFigure.add(obj, index + 1);
        }
    }

    public void remove(IFigure figure) {
        if(figure instanceof  AttributeLabel){
            attributeFigure.remove(figure);
        } else if(figure instanceof OperationLabel){
            methodFigure.remove(figure);
        } else {
            super.remove(figure);
        }
    }

    public Label getLabel(){
        return name;
    }

    public Rectangle getCellEditorRectangle() {
        Rectangle rect = name.getBounds().getCopy();
        if (name.getIcon() != null) {
            return new Rectangle(rect.x + 16, rect.y, rect.width - 16, rect.height);
        }
        return new Rectangle(rect.x, rect.y, rect.width, rect.height);
    }

    public void updatePresentation(AbstractUMLModel model) {
        if (model.isShowIcon()) {
            name.setIcon(icon);
        } else {
            name.setIcon(null);
        }
    }

    public void setStereoType(String stereoType) {
        if (stereoType == null || "".equals(stereoType)) {
            if (nameFigure.getChildren().contains(this.stereoType)) {
                nameFigure.remove(this.stereoType);
            }
        } else {
            this.stereoType.setText("<<" + stereoType + ">>");
            if (!nameFigure.getChildren().contains(this.stereoType)) {
                nameFigure.add(this.stereoType, 0);
            }
        }
    }
}

在GEF框架中,Modal是非常简单的一部分,用户可以把Modal理解成一个简单的可持久化的实体。但为了能让控制器知道模型的变化,应该控制器作为事件监听者注册到Modal中,当模型发生变化时,就触发相应的事件给控制器,后者负责通知各个视图进行更新。
典型的模型对象包含PropertyChangeSupport类型的成员变量,用来添加监听器和通知监听器(控制器),一般来说,模型会实现一个基类,用来封装事件机制,主要包括添加监听器,删除监听器,以及模型属性改变触发的相应事件。另外,当用户希望通过属性视图编辑模型属性时,模型要实现IPropertySource接口,该接口的方法解释如下:

//得到在属性页中能编辑的值,可以返回this表示当前模型
public Object getEditableValue();
//得到IPropertyDescriptor的数组,其中每一项是属性页中能编辑的项
public IPropertyDescriptor[] getPropertyDescriptors();
//通过id得到某个属性值,在添加每一项IPropertyDescriptor都会指定id
public Object getPropertyValue(Object id);
//表示特定属性id值是否改变
public boolean isPropertySet(Object id);
public void resetPropertyValue(Object id);//通过id重置属性
public void setPropertyValue(Object id, Object value);//通过id和值设置某一项属性的值

类图如下:
技术分享

我们定义一个AbstractUMLModel 封装事件机制和属性编辑

public abstract class AbstractUMLModel implements Serializable, IPropertySource {

    //定义属性的常量ID
    public static final String P_BACKGROUND_COLOR = "_background";

    public static final String P_FOREGROUND_COLOR = "_foreground";

    public static final String P_SHOW_ICON = "_showicon";

    private RGB backgroundColor;

    private RGB foregroundColor;

    private boolean showIcon = true;

    private AbstractUMLEntityModel parent;


    private PropertyChangeSupport listeners = new PropertyChangeSupport(this);


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


    public void firePropertyChange(String propName, Object oldValue,Object newValue) {
        listeners.firePropertyChange(propName, oldValue, newValue);
    }


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

    public Object getEditableValue() {
        return this;
    }

    public void setParent(AbstractUMLEntityModel parent) {
        this.parent = parent;
    }

    public AbstractUMLEntityModel getParent() {
        return parent;
    }


    public IPropertyDescriptor[] getPropertyDescriptors() {
        //定义属性的编辑项 
        return new IPropertyDescriptor[] {
                new ColorPropertyDescriptor(P_BACKGROUND_COLOR, "Background Color"),
                new ColorPropertyDescriptor(P_FOREGROUND_COLOR, "Foreground Color"),
                //自定义的PropertyDescriptor
                new BooleanPropertyDescriptor(P_SHOW_ICON, "Show Icon") };

    }

    public Object getPropertyValue(Object id) {
        if (id.equals(P_BACKGROUND_COLOR)) {
            return backgroundColor;
        } else if (P_FOREGROUND_COLOR.equals(id)) {
            return foregroundColor;
        } else if (P_SHOW_ICON.equals(id)) {
            return new Boolean(isShowIcon());
        }
        return null;
    }

    public boolean isPropertySet(Object id) {
        return P_BACKGROUND_COLOR.equals(id) || P_FOREGROUND_COLOR.equals(id)
                || P_SHOW_ICON.equals(id);
    }

     //设置属性的值 
    public void setPropertyValue(Object id, Object value) {
        if (P_BACKGROUND_COLOR.equals(id)) {
            setBackgroundColor((RGB) value);
        } else if (P_FOREGROUND_COLOR.equals(id)) {
            setForegroundColor((RGB) value);
        } else if (P_SHOW_ICON.equals(id)) {
            setShowIcon(((Boolean) value).booleanValue());
        }
    }

    public void resetPropertyValue(Object id) {
    }

    public Color getBackgroundColor() {
        //调用自定义生成颜色对象
        return UMLColorRegistry.getColor(backgroundColor);
    }

    public void setBackgroundColor(RGB backgroundColor) {
        this.backgroundColor = backgroundColor;
        //当backgroundColor改变后,触发属性改变的事件
        firePropertyChange(P_BACKGROUND_COLOR, null, backgroundColor);
    }

    public Color getForegroundColor() {
        return UMLColorRegistry.getColor(foregroundColor);
    }

    public void setForegroundColor(RGB foregroundColor) {
        this.foregroundColor = foregroundColor;
        //当foregroundColor改变后,触发属性改变的事件 
        firePropertyChange(P_FOREGROUND_COLOR, null, foregroundColor);
    }

    public boolean isShowIcon() {
        return showIcon;
    }

    public void setShowIcon(boolean showIcon) {
        this.showIcon = showIcon;
        //当SHOW_ICON改变后,触发属性改变的事件 
        firePropertyChange(P_SHOW_ICON, null, new Boolean(showIcon));
    }

    public void copyPresentation(AbstractUMLModel model) {
        if (backgroundColor != null) {
            model.setBackgroundColor(backgroundColor);
        }
        if (foregroundColor != null) {
            model.setForegroundColor(foregroundColor);
        }
        model.setShowIcon(showIcon);
    }
}

AbstractUMLEntityModel代码如下:

public abstract class AbstractUMLEntityModel extends AbstractUMLModel {


    private Rectangle constraint;
    //定义模型连线的列表
    private List<AbstractUMLConnectionModel> sourceConnections = new ArrayList<AbstractUMLConnectionModel>();
    private List<AbstractUMLConnectionModel> targetConnections = new ArrayList<AbstractUMLConnectionModel>();

    private List<AbstractUMLModel> children = new ArrayList<AbstractUMLModel>();
    private Map<String, Boolean> filterProperty = new HashMap<String, Boolean>();

    //定义属性的常量ID   
    public static final String P_CONSTRAINT = "_constraint";
    public static final String P_SOURCE_CONNECTION = "_source_connection";
    public static final String P_TARGET_CONNECTION = "_target_connection";
    public static final String P_CHILDREN = "_children";
    public static final String P_FILTER = "_filter";
    public static final String P_FORCE_UPDATE = "_force_update";

    public Map<String, Boolean> getFilterProperty() {
        return filterProperty;
    }

    public void setFilterProperty(Map<String, Boolean> filterProperty) {
        this.filterProperty = filterProperty;
        firePropertyChange(P_FILTER, null, filterProperty);
    }

    public Rectangle getConstraint() {
        return constraint;
    }

    public void addChild(AbstractUMLModel model) {
        children.add(model);
        model.setParent(this);
        //当增加子模型时,触发属性改变的事件
        firePropertyChange(P_CHILDREN,null,model);
    }

    public void removeChild(AbstractUMLModel model) {
        children.remove(model);
        model.setParent(this);
        //当删除子模型时,触发属性改变的事件 
        firePropertyChange(P_CHILDREN,null,model);
    }

    public void forceUpdate() {
        firePropertyChange(P_FORCE_UPDATE, null ,null);
    }

    public List<AbstractUMLModel> getChildren(){
        return this.children;
    }

    public void setConstraint(Rectangle constraint) {
        if(constraint.x < 0){
            constraint.x = 0;
        }
        if(constraint.y < 0){
            constraint.y = 0;
        }
        this.constraint = constraint;
        firePropertyChange(P_CONSTRAINT, null, constraint);
    }

    public void addSourceConnection(AbstractUMLConnectionModel connx) {
        sourceConnections.add(connx);
        //当输入的连线改变后,触发属性改变的事件 
        firePropertyChange(P_SOURCE_CONNECTION, null, connx);
    }

    public void addTargetConnection(AbstractUMLConnectionModel connx) {
        targetConnections.add(connx);
        //当输入的连线改变后,触发属性改变的事件 
        firePropertyChange(P_TARGET_CONNECTION, null, connx);
    }

    public List<AbstractUMLConnectionModel> getModelSourceConnections() {
        return sourceConnections;
    }

    public List<AbstractUMLConnectionModel> getModelTargetConnections() {
        return targetConnections;
    }

    public void removeSourceConnection(AbstractUMLConnectionModel connx) {
        sourceConnections.remove(connx);
        //当输入的连线改变后,触发属性改变的事件 
        firePropertyChange(P_SOURCE_CONNECTION, connx, null);
    }

    public void removeTargetConnection(AbstractUMLConnectionModel connx) {
        targetConnections.remove(connx);
        //当输入的连线改变后,触发属性改变的事件 
        firePropertyChange(P_TARGET_CONNECTION, connx, null);
    }

    public void setBackgroundColor(RGB backgroundColor) {
        for (Iterator<AbstractUMLModel> iter = children.iterator(); iter.hasNext();) {
            AbstractUMLModel element = (AbstractUMLModel) iter.next();
            element.setBackgroundColor(backgroundColor);
        }
        super.setBackgroundColor(backgroundColor);
    }

    public void setForegroundColor(RGB foregroundColor) {
        for (Iterator<AbstractUMLModel> iter = children.iterator(); iter.hasNext();) {
            AbstractUMLModel element = (AbstractUMLModel) iter.next();
            element.setForegroundColor(foregroundColor);
        }
        super.setForegroundColor(foregroundColor);
    }

    public void setShowIcon(boolean showIcon) {
        for (Iterator<AbstractUMLModel> iter = children.iterator(); iter.hasNext();) {
            AbstractUMLModel element = (AbstractUMLModel) iter.next();
            element.setShowIcon(showIcon);
        }
        super.setShowIcon(showIcon);
    }
}

AbstractUMLConnectionModel,分析方法跟上面的都类似:

public abstract class AbstractUMLConnectionModel extends AbstractUMLModel {

    private AbstractUMLEntityModel source;

    private AbstractUMLEntityModel target;

    private List<ConnectionBendpoint> bendpoints = new ArrayList<ConnectionBendpoint>();

    public static final String P_BEND_POINT = "_bend_point";

    public void addBendpoint(int index, ConnectionBendpoint point) {
        bendpoints.add(index, point);
        firePropertyChange(P_BEND_POINT, null, null);
    }



    public List<ConnectionBendpoint> getBendpoints() {
        if (bendpoints == null) {
            bendpoints = new ArrayList<ConnectionBendpoint>();
        }
        return bendpoints;
    }

    public void removeBendpoint(int index) {
        bendpoints.remove(index);
        firePropertyChange(P_BEND_POINT, null, null);
    }

    public void removeBendpoint(ConnectionBendpoint point) {
        bendpoints.remove(point);
        firePropertyChange(P_BEND_POINT, null, null);
    }

    public void replaceBendpoint(int index, ConnectionBendpoint point) {
        bendpoints.set(index, point);
        firePropertyChange(P_BEND_POINT, null, null);
    }




    public void attachSource() {

        if (!source.getModelSourceConnections().contains(this)) {
            source.addSourceConnection(this);
        }
    }


    public void attachTarget() {
        if (!target.getModelTargetConnections().contains(this)) {
            target.addTargetConnection(this);
        }
    }


    public void detachSource() {
        if (source != null) {
            source.removeSourceConnection(this);
        }
    }


    public void detachTarget() {
        if (target != null) {
            target.removeTargetConnection(this);
        }
    }

    public AbstractUMLEntityModel getSource() {
        return source;
    }

    public AbstractUMLEntityModel getTarget() {
        return target;
    }

    public void setSource(AbstractUMLEntityModel model) {
        source = model;
    }

    public void setTarget(AbstractUMLEntityModel model) {
        target = model;
    }

    public IPropertyDescriptor[] getPropertyDescriptors() {
        return new IPropertyDescriptor[] {
                new ColorPropertyDescriptor(P_FOREGROUND_COLOR, "Foreground Color")
                };
    }

}

ConnectionBendpoint类如下:

public class ConnectionBendpoint implements Serializable, Bendpoint {

    private float weight = 0.5f;

    private Dimension d1 = null;

    private Dimension d2 = null;

    public ConnectionBendpoint() {
        // ignore
    }

    public ConnectionBendpoint(Dimension dim1, Dimension dim2) {
        d1 = dim1;
        d2 = dim2;
    }

    public Dimension getFirstRelativeDimension() {
        return d1;
    }

    public Point getLocation() {
        return null;
    }

    public Dimension getSecondRelativeDimension() {
        return d2;
    }

    public float getWeight() {
        return weight;
    }

    public void setRelativeDimensions(Dimension dim1, Dimension dim2) {
        d1 = dim1;
        d2 = dim2;
    }

    public void setWeight(float w) {
        weight = w;
    }
}

UMLColorRegistry类如下:

public class UMLColorRegistry {

    private ColorRegistry registry;

    private static UMLColorRegistry instance;

    private UMLColorRegistry() {
        registry = new ColorRegistry();
    }
    //单例
    public static final Color getColor(RGB rgb) {
        if (instance == null) {
            instance = new UMLColorRegistry();
        }
        if (rgb == null) {
            return null;
        }
        return instance.createColor(rgb);
    }

    //获取颜色对象
    private Color createColor(RGB rgb) {
        registry.put(rgb.toString(), rgb);
        return registry.get(rgb.toString());
    }

}

BooleanPropertyDescriptor类如下:

public class BooleanPropertyDescriptor extends PropertyDescriptor {

    public BooleanPropertyDescriptor(Object id,String displayName){
        super(id,displayName);
    }

    public CellEditor createPropertyEditor(Composite parent) {
        CellEditor editor = new ComboBoxCellEditor(
                parent, new String[]{"true","false"},SWT.READ_ONLY){
            public void doSetValue(Object value){
                if(((Boolean)value).booleanValue()){
                    super.doSetValue(new Integer(0));
                } else {
                    super.doSetValue(new Integer(1));
                }
            }
            public Object doGetValue(){
                int selection = ((Integer)super.doGetValue()).intValue();
                if(selection==0){
                    return new Boolean(true);
                } else {
                    return new Boolean(false);
                }
            }
        };

        if (getValidator() != null)
            editor.setValidator(getValidator());

        return editor;
    }
}

现在对于UML的抽象类已经大致看到了外貌,主要是把Figure与Model做了较详细的介绍,以及详细的代码,但是还是停留在抽象层面,下一篇文章主要针对UMLClass类图的具体类进行分析。

Eclipse GEF UMLClass(1)

标签:

原文地址:http://blog.csdn.net/niujiabinbin/article/details/51351934

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!