GEF的模型只与控制器打交道,而不知道任何与视图有关的东西。
1.模型的功能
在GEF框架中,模型(Model)是非常简单的一部分,用户可把模型理解成一个简单的可持久化的实体。但为了能让控制器知道模型的变化,应该把控制器作为事件监听者注册在模型中,当模型发生变化时,就触发相应的事件给控制器,后者负责通知各个视图进行更新。
2.模型的实现
典型的模型对象会包含PropertyChangeSupport类型的成员变量,用来触发事件,通知监听器即控制器。一般来说,模型会实现一个基类,用来封装事件机制,主要包括添加监听器、删除监听器,以及模型属性改变触发的相应事件,代码如下:
另外,当用户希望通过属性视图编辑模型属性时,模型要实现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和值设置某一项属性的值
}
如果模型和其它模型有关系(在视图上为连线),模型要维护这些关系,并适当的持久化,当模型的属性修改后,模型要触发相应的事件通知监听器。
上例中实现了模型对应的属性视图,当属性被修改后,模型将会调用“fire...”方法触发相应的模型改变事件。
1.模型的功能
在GEF框架中,模型(Model)是非常简单的一部分,用户可把模型理解成一个简单的可持久化的实体。但为了能让控制器知道模型的变化,应该把控制器作为事件监听者注册在模型中,当模型发生变化时,就触发相应的事件给控制器,后者负责通知各个视图进行更新。
2.模型的实现
典型的模型对象会包含PropertyChangeSupport类型的成员变量,用来触发事件,通知监听器即控制器。一般来说,模型会实现一个基类,用来封装事件机制,主要包括添加监听器、删除监听器,以及模型属性改变触发的相应事件,代码如下:
java 代码
package com.example.model; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.Serializable; public abstract class Element implements Cloneable, Serializable { PropertyChangeSupport listeners = new PropertyChangeSupport(this); //添加监听器 public void addPropertyChangeListener(PropertyChangeListener l) { listeners.addPropertyChangeListener(l); } //触发属性改变的事件 protected void firePropertyChange(String prop, Object old, Object newValue) { listeners.firePropertyChange(prop, old, newValue); } //触发结构改变的事件 protected void fireStructureChange(String prop, Object child) { listeners.firePropertyChange(prop, null, child); } // private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { // in.defaultReadObject(); // listeners = new PropertyChangeSupport(this); // } //删除监听器 public void removePropertyChangeListener(PropertyChangeListener l) { listeners.removePropertyChangeListener(l); } }
另外,当用户希望通过属性视图编辑模型属性时,模型要实现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 代码
package com.example.model; import java.util.ArrayList; import java.util.List; import org.eclipse.draw2d.geometry.Point; import org.eclipse.ui.views.properties.ComboBoxPropertyDescriptor; import org.eclipse.ui.views.properties.IPropertyDescriptor; import org.eclipse.ui.views.properties.IPropertySource; import org.eclipse.ui.views.properties.TextPropertyDescriptor; public class Node extends Element implements IPropertySource { //定义属性的常量ID final public static String PROP_LOCATION = "LOCATION"; final public static String PROP_NAME = "NAME"; final public static String PROP_VISIBLE = "VISIBLE"; final public static String PROP_INPUTS = "INPUTS"; final public static String PROP_OUTPUTS = "OUTPUTS"; protected Point location = new Point(0, 0); protected String name = "Node"; protected boolean visible = true; //定义属性的编辑项 protected IPropertyDescriptor[] descriptors = new IPropertyDescriptor[] { new TextPropertyDescriptor(PROP_NAME, "Name"), new ComboBoxPropertyDescriptor(PROP_VISIBLE, "Visible", new String[] { "true", "false" }) }; //定义模型连线的列表 protected List outputs = new ArrayList(5); protected List inputs = new ArrayList(5); public void addInput(Connection connection) { this.inputs.add(connection); //当输入的连线改变后,触发结构改变的事件 fireStructureChange(PROP_INPUTS, connection); } public void addOutput(Connection connection) { this.outputs.add(connection); //当输出的连线改变后,触发结构改变的事件 fireStructureChange(PROP_OUTPUTS, connection); } public List getIncomingConnections() { return this.inputs; } public List getOutgoingConnections() { return this.outputs; } public void removeInput(Connection connection) { this.inputs.remove(connection); fireStructureChange(PROP_INPUTS, connection); } public void removeOutput(Connection connection) { this.outputs.remove(connection); fireStructureChange(PROP_OUTPUTS, connection); } public boolean isVisible() { return visible; } public void setVisible(boolean visible) { if (this.visible == visible) { return; } this.visible = visible; firePropertyChange(PROP_VISIBLE, null, Boolean.valueOf(visible)); } public String getName() { return name; } public void setName(String name) { if (this.name.equals(name)) { return; } this.name = name; //当模型的名字改变后,通知监听器更新名字的显示 firePropertyChange(PROP_NAME, null, name); } public void setLocation(Point p) { if (this.location.equals(p)) { return; } this.location = p; //当模型的位置改变后,通知监听器更新模型的位置 firePropertyChange(PROP_LOCATION, null, p); } public Point getLocation() { return location; } //------------------------------------------------------------------------ // Abstract methods from IPropertySource public Object getEditableValue() { return this; } //得到属性编辑项 public IPropertyDescriptor[] getPropertyDescriptors() { return descriptors; } //得到属性编辑项的值 public Object getPropertyValue(Object id) { if (PROP_NAME.equals(id)) return getName(); if (PROP_VISIBLE.equals(id)) return isVisible() ? new Integer(0) : new Integer(1); return null; } public boolean isPropertySet(Object id) { return true; } public void resetPropertyValue(Object id) { } //设置属性的值 public void setPropertyValue(Object id, Object value) { if (PROP_NAME.equals(id)) setName((String) value); if (PROP_VISIBLE.equals(id)) setVisible(((Integer) value).intValue() == 0); } }
上例中实现了模型对应的属性视图,当属性被修改后,模型将会调用“fire...”方法触发相应的模型改变事件。