之前我还是要说,学习GEF,如果你没有学过Eclipse插件,那么最好先花时间熟悉一下Eclipse的插件体系结构,在这里我只介绍GEF的相关知识,swt以及eclipse plug-in的东西还需自己学习.(为此偶花了100大元买了IBM的eclipse 开发指南

从前面的介绍中我们知道,GEF采用MVC模式,所以我们就从模型开始.
模型实现的功能主要有以下几个方面:(1)存储了所有用户可以编辑或浏览的数据,包括可视化相关的数据比如大小,坐标等
(2)提供可持久化模型的方法,当编辑器关闭时你的模型被持久化.打开后还应恢复.
(3)提供方法允许 别人监听他的变化,前面的介绍中我们知道,控制要知道模型的变化.并作出相应的相应.
根据以上三个方面我们在看DEMO的要求.三角,矩形,圆形均他们具有相同的特征,所以我们不妨将其抽象为ShapeModel类,由于模型的属性变化了,必须通知控制器,由它来刷新模型对应的视图,所以控制器必须注册为模型的侦听器。由于每个模型都有相应的控制器侦听器侦听它属性的变化,我们把这方面的功能都放在父类中,定义一个ElementModel父类(觉得这个挺好,网上的各种示例都这么干的)
所以我们先来看看模型ElementModel父类的代码:

















































































从中可以看到为了持久化,我们让其实现了
java.io.Serializable
接口以及readObject方法.同时我为了提供监听机制,我们引入了PropertyChangeSupport对象,同时添加addPropertyChangeListener和addPropertyChangeListener两个方法来提供监听器的注册和移除.同时提供firePropertyChange(String property, Object oldValue,Object newValue) 方法来同志监听器模型属性发生了变化.
然后我们在来看我们的抽象图形类,取名为ShapeModel

/** *//**
* 图形的公共基类
* <UL>
* <LI>所有图形继承此类<LI>
* <LI>抽象了图形的公共属性位置,大小,以及连线<LI>
* </UL>
* @author hya
* */

public abstract class ShapeModel extends ElementModel
{

/** *//**坐标改变的ID, 用于通知监听器图形坐标放生改变 */
public static final String LOCATION_PROP = "Model.Location";
private static final long serialVersionUID = 1;

/** *//** 大小改变的ID,通知监听器图形大小放生改变 */
public static final String SIZE_PROP = "Model.Size";

/** *//**以下连个为连接ID,用于通知监听器图形的连接发生改变 */
public static final String SOURCE_CONNECTIONS_PROP = "Model.SourceConn";
public static final String TARGET_CONNECTIONS_PROP = "Model.TargetConn";



/** *//** 图形坐标 */
private Point location = new Point(0, 0);

/** *//** 图形大小 */
private Dimension size = new Dimension(50, 50);

/** *//** 图形作为连接源点的列表 */
private List sourceConnections = new ArrayList();

/** *//** 图形作为连接终点的列表*/
private List targetConnections = new ArrayList();


/** *//**
* 图形增加连接
*/

void addConnection(Connection conn)
{

if (conn == null || conn.getSource() == conn.getTarget())
{
throw new IllegalArgumentException();
}

if (conn.getSource() == this)
{
sourceConnections.add(conn);
firePropertyChange(SOURCE_CONNECTIONS_PROP, null, conn);

} else if (conn.getTarget() == this)
{
targetConnections.add(conn);
firePropertyChange(TARGET_CONNECTIONS_PROP, null, conn);
}
}


/** *//**
* 根据路径得到图标
* 相对于类Activator
* */

protected static Image createImage(String name)
{
InputStream stream = Activator.class.getResourceAsStream(name);
Image image = new Image(null, stream);

try
{
stream.close();

} catch (IOException ioe)
{
}
return image;
}

/** *//**
*定义元素模型图标
*子类应实现它
*/
public abstract Image getIcon();


/** *//**
* 得到图形坐标
*/

public Point getLocation()
{
return location.getCopy();
}




/** *//**
* 得到图形大小
*/

public Dimension getSize()
{
return size.getCopy();
}



public List getSourceConnections()
{
return new ArrayList(sourceConnections);
}


public List getTargetConnections()
{
return new ArrayList(targetConnections);
}


/** *//**
*移出连接
*/

public void removeConnection(Connection conn)
{

if (conn == null)
{
throw new IllegalArgumentException();
}

if (conn.getSource() == this)
{
sourceConnections.remove(conn);
firePropertyChange(SOURCE_CONNECTIONS_PROP, null, conn);

} else if (conn.getTarget() == this)
{
targetConnections.remove(conn);
firePropertyChange(TARGET_CONNECTIONS_PROP, null, conn);
}
}


/** *//**
* 改变图形坐标
*/

public void setLocation(Point newLocation)
{

if (newLocation == null)
{
throw new IllegalArgumentException();
}
location.setLocation(newLocation);
firePropertyChange(LOCATION_PROP, null, location);
}




/** *//**
*改变图形大小
*/

public void setSize(Dimension newSize)
{

if (newSize != null)
{
size.setSize(newSize);
firePropertyChange(SIZE_PROP, null, size);
}
}
}

由于图形之间要有连线,这个连线通常是有方向的所以我们提供了两个List来分别存储源连接和目标连接。源连接是指那些以当前图形作为源的连接,目标连接是指以当前图形作为目标的连接。同时的还有两个对象属性location,size 来表示图形的坐标和大小。同时提供了各自的方法来维护这些属性,我们应该注意到每次模型发生改变时都会调用firePropertyChange();来通知监视器模型有改变,他维护了三个参数第一个为属性表示,是我们自己定义的用来告诉监视器那个属性有变化以及变化的值。(看到这里你是不是会想到什么,对就是观察者模式,属性监听机制就是用了观察者模式)。
三个图形的只是对它的扩展



























是不是忘了什么,对就是连接线模型








































































































原理和上面一样,在下一天中我们会来讨论GEF的核心控制器。