`
LuChar
  • 浏览: 74146 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

GEF原理及实现系列(二、模型)

    博客分类:
  • GEF
阅读更多
GEF的模型只与控制器打交道,而不知道任何与视图有关的东西。
1.模型的功能
    在GEF框架中,模型(Model)是非常简单的一部分,用户可把模型理解成一个简单的可持久化的实体。但为了能让控制器知道模型的变化,应该把控制器作为事件监听者注册在模型中,当模型发生变化时,就触发相应的事件给控制器,后者负责通知各个视图进行更新。
2.模型的实现
    典型的模型对象会包含PropertyChangeSupport类型的成员变量,用来触发事件,通知监听器即控制器。一般来说,模型会实现一个基类,用来封装事件机制,主要包括添加监听器、删除监听器,以及模型属性改变触发的相应事件,代码如下:
java 代码
 
  1. package com.example.model;  
  2.   
  3. import java.beans.PropertyChangeListener;  
  4. import java.beans.PropertyChangeSupport;  
  5. import java.io.Serializable;  
  6.   
  7. public abstract class Element implements Cloneable, Serializable {  
  8.   
  9.     PropertyChangeSupport listeners = new PropertyChangeSupport(this);  
  10.     //添加监听器  
  11.     public void addPropertyChangeListener(PropertyChangeListener l) {  
  12.         listeners.addPropertyChangeListener(l);  
  13.     }  
  14.     //触发属性改变的事件  
  15.     protected void firePropertyChange(String prop, Object old, Object newValue) {  
  16.         listeners.firePropertyChange(prop, old, newValue);  
  17.     }  
  18.     //触发结构改变的事件  
  19.     protected void fireStructureChange(String prop, Object child) {  
  20.         listeners.firePropertyChange(prop, null, child);  
  21.     }  
  22.   
  23. //    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {  
  24. //        in.defaultReadObject();  
  25. //        listeners = new PropertyChangeSupport(this);  
  26. //    }  
  27.     //删除监听器  
  28.     public void removePropertyChangeListener(PropertyChangeListener l) {  
  29.         listeners.removePropertyChangeListener(l);  
  30.     }  
  31.   
  32. }  

    另外,当用户希望通过属性视图编辑模型属性时,模型要实现IPropertySource接口,该接口的方法解释如下:
   
package org.eclipse.ui.views.properties;

public interface IPropertySource {

    public Object getEditableValue();//得到在属性页中能编辑的值,可以返回this表示当前模型

    public IPropertyDescriptor[] getPropertyDescriptors();//得到IPropertyDescriptor类型的数组,其中每一项为属性页中能编辑的项
   
    public Object getPropertyValue(Object id);//通过id值得到某个属性,在添加每一项IPropertyDescriptor时都会指定id值

    public boolean isPropertySet(Object id);//表示特定属性id值是否改变

    public void resetPropertyValue(Object id);//通过id重置属性

    public void setPropertyValue(Object id, Object value);//通过id和值设置某一项属性的值
}
    如果模型和其它模型有关系(在视图上为连线),模型要维护这些关系,并适当的持久化,当模型的属性修改后,模型要触发相应的事件通知监听器。
java 代码
 
  1. package com.example.model;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import org.eclipse.draw2d.geometry.Point;  
  7. import org.eclipse.ui.views.properties.ComboBoxPropertyDescriptor;  
  8. import org.eclipse.ui.views.properties.IPropertyDescriptor;  
  9. import org.eclipse.ui.views.properties.IPropertySource;  
  10. import org.eclipse.ui.views.properties.TextPropertyDescriptor;  
  11.   
  12. public class Node extends Element implements IPropertySource {  
  13.     //定义属性的常量ID   
  14.     final public static String PROP_LOCATION = "LOCATION";  
  15.   
  16.     final public static String PROP_NAME = "NAME";  
  17.   
  18.     final public static String PROP_VISIBLE = "VISIBLE";  
  19.   
  20.     final public static String PROP_INPUTS = "INPUTS";  
  21.   
  22.     final public static String PROP_OUTPUTS = "OUTPUTS";  
  23.   
  24.     protected Point location = new Point(00);  
  25.   
  26.     protected String name = "Node";  
  27.   
  28.     protected boolean visible = true;  
  29.     //定义属性的编辑项  
  30.     protected IPropertyDescriptor[] descriptors = new IPropertyDescriptor[] {  
  31.             new TextPropertyDescriptor(PROP_NAME, "Name"),  
  32.             new ComboBoxPropertyDescriptor(PROP_VISIBLE, "Visible"new String[] { "true""false" }) };  
  33.     //定义模型连线的列表  
  34.     protected List outputs = new ArrayList(5);  
  35.   
  36.     protected List inputs = new ArrayList(5);  
  37.   
  38.     public void addInput(Connection connection) {  
  39.         this.inputs.add(connection);  
  40.         //当输入的连线改变后,触发结构改变的事件  
  41.         fireStructureChange(PROP_INPUTS, connection);  
  42.     }  
  43.   
  44.     public void addOutput(Connection connection) {  
  45.         this.outputs.add(connection);  
  46.       //当输出的连线改变后,触发结构改变的事件  
  47.         fireStructureChange(PROP_OUTPUTS, connection);  
  48.     }  
  49.   
  50.     public List getIncomingConnections() {  
  51.         return this.inputs;  
  52.     }  
  53.   
  54.     public List getOutgoingConnections() {  
  55.         return this.outputs;  
  56.     }  
  57.   
  58.     public void removeInput(Connection connection) {  
  59.         this.inputs.remove(connection);  
  60.         fireStructureChange(PROP_INPUTS, connection);  
  61.     }  
  62.   
  63.     public void removeOutput(Connection connection) {  
  64.         this.outputs.remove(connection);  
  65.         fireStructureChange(PROP_OUTPUTS, connection);  
  66.     }  
  67.   
  68.     public boolean isVisible() {  
  69.         return visible;  
  70.     }  
  71.   
  72.     public void setVisible(boolean visible) {  
  73.         if (this.visible == visible) {  
  74.             return;  
  75.         }  
  76.         this.visible = visible;  
  77.         firePropertyChange(PROP_VISIBLE, null, Boolean.valueOf(visible));  
  78.     }  
  79.   
  80.     public String getName() {  
  81.         return name;  
  82.     }  
  83.   
  84.     public void setName(String name) {  
  85.         if (this.name.equals(name)) {  
  86.             return;  
  87.         }  
  88.         this.name = name;  
  89.         //当模型的名字改变后,通知监听器更新名字的显示  
  90.         firePropertyChange(PROP_NAME, null, name);  
  91.     }  
  92.   
  93.     public void setLocation(Point p) {  
  94.         if (this.location.equals(p)) {  
  95.             return;  
  96.         }  
  97.         this.location = p;  
  98.       //当模型的位置改变后,通知监听器更新模型的位置  
  99.         firePropertyChange(PROP_LOCATION, null, p);  
  100.     }  
  101.   
  102.     public Point getLocation() {  
  103.         return location;  
  104.     }  
  105.   
  106.     //------------------------------------------------------------------------  
  107.     // Abstract methods from IPropertySource  
  108.   
  109.     public Object getEditableValue() {  
  110.         return this;  
  111.     }  
  112.     //得到属性编辑项  
  113.     public IPropertyDescriptor[] getPropertyDescriptors() {  
  114.         return descriptors;  
  115.     }  
  116.     //得到属性编辑项的值  
  117.     public Object getPropertyValue(Object id) {  
  118.         if (PROP_NAME.equals(id))  
  119.             return getName();  
  120.         if (PROP_VISIBLE.equals(id))  
  121.             return isVisible() ? new Integer(0) : new Integer(1);  
  122.         return null;  
  123.     }  
  124.   
  125.     public boolean isPropertySet(Object id) {  
  126.         return true;  
  127.     }  
  128.   
  129.     public void resetPropertyValue(Object id) {  
  130.   
  131.     }  
  132.     //设置属性的值  
  133.     public void setPropertyValue(Object id, Object value) {  
  134.         if (PROP_NAME.equals(id))  
  135.             setName((String) value);  
  136.         if (PROP_VISIBLE.equals(id))  
  137.             setVisible(((Integer) value).intValue() == 0);  
  138.     }  
  139. }  

    上例中实现了模型对应的属性视图,当属性被修改后,模型将会调用“fire...”方法触发相应的模型改变事件。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics