Eclipse GEF UMLClass(1)

来源:互联网 发布:windows xp sp3繁体版 编辑:程序博客网 时间:2024/04/29 14:34

通过两篇文章对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类图的具体类进行分析。

1 0