由GEF所构建的图形编辑器用户通常的操作流程描述如下:
1、创建需要绘制图形的文件,并根据文件类型使用相应的编辑器打开文件,为绘制工作初始化一个图形编辑视图。
2、根据图形编辑器所提供的图元工具创建具体图元,将图元绘制于编辑器所提供的图形编辑视图之上
3、已绘制图形元素的持久化
根据这个流程,GEF中的各个类所需要执行的操作基本步骤如下:
1、创建文件,根据文件类型选择相应的Editor及Editor和相关的Viewer的初始化(此部分在以后会详细说明)
2、使用Editor所提供的Palette在Viewer上绘制图形
a、用户选择想要绘制的图元,EditDomain会将用户选择的Palette中的相应的ToolEntry激活。
private void handlePaletteToolChanged()
{
ToolEntry entry = getPaletteViewer().getActiveTool();
if (entry !=null)
setActiveTool(entry.createTool());
else
setActiveTool(getDefaultTool());
}
b、用户在画板视图上按下鼠标左键后,DomainEventDispatcher会监听鼠标事件
/**
* @see EventDispatcher#dispatchMousePressed(org.eclipse.swt.events.MouseEvent)
*/
public void dispatchMousePressed(org.eclipse.swt.events.MouseEvent me)
{
if (!editorCaptured)
{
super.dispatchMousePressed(me);
if (draw2dBusy())
return;
}
if (okToDispatch())
{
setFocus(null);
control.forceFocus();
setRouteEventsToEditor(true);
domain.mouseDown(me, viewer);
}
}
然后根据事件相应的类型将其路由到EditDomain,EditDomain则根据事件的类型执行相应的操作。这些操作的主要工作就是获取EditDomain中当前被激活的工具(getActiveTool()),然后执行该工具对这些鼠标事件的响应。
public void mouseDown(MouseEvent mouseEvent, EditPartViewer viewer)
{
Tool tool = getActiveTool();
if (tool !=null)
tool.mouseDown(mouseEvent, viewer);
}
以CreationTool为例,它对ButtonDown事件的响应(handleButtonDown(int))就是创建一个CreateRequest,并赋予其相应的位置信息(setLocation(Point))
/**
* The creation tool only works by clicking mouse button 1 (the left mouse button in a
* right-handed world). If any other button is pressed, the tool goes into an invalid
* state. Otherwise, it goes into the drag state, updates the request's location and
* calls {@link TargetingTool#lockTargetEditPart(EditPart)} with the edit part that was
* just clicked on.
*
* @see org.eclipse.gef.tools.AbstractTool#handleButtonDown(int)
*/
protected boolean handleButtonDown(int button)
{
if (button !=1)
{
setState(STATE_INVALID);
handleInvalidInput();
return true;
}
if (stateTransition(STATE_INITIAL, STATE_DRAG))
{
getCreateRequest().setLocation(getLocation());
lockTargetEditPart(getTargetEditPart());
// Snap only when size on drop is employed
helper = (SnapToHelper)getTargetEditPart().getAdapter(SnapToHelper.class);
}
return true;
}
c、CreationTool还会根据Request的类型及位置将其分派给相应的EditPart。[Targeting tools work with a target request. This request is used along with the mouse location to obtain an active target from the current EditPartViewer. This target is then asked for the Command that performs the given request. The target is also asked to show target feedback. (摘自org.eclipse.gef.tools.TargetingTool)]
d、此后的流程基本上就如GEF EMF Redbook中3.3.3Requests节中的Communication chain
Request-EditPart-Command所述
Command执行所做的操作只是对它所涉及到的模型进行相应的设置,譬如大小、位置、颜色等属性。那么图元如何显示在视图之上呢?这一部分正是由GEF中所使用的MVC模式实现。
GEF中的每一个模型都实现了某种Notifier(org.eclipse.emf.common.notify.Notifier)或者IPropertySource(org.eclipse.ui.views.properties.IPropertySource)接口作为消息源,每个EditPart则相应的实现了Adapter(org.eclipse.emf.common.notify.Adapter)或PropertyChangeListener(java.beans.PropertyChangeListener)等接口作为侦听器。并在EditPart初始化时,将其本身注册为所对应的模型的一个侦听器,当模型中的属性发生变化时,EditPart会执行相应的操作。
在EditPart初始化时,将其本身注册为所对应的模型的一个侦听器,并在销毁之前注销注册:
/**
* Upon activation, attach to the model element as a notification change
* listener.
*/
public void activate() {
if (!isActive()) {
super.activate();
((ModelElement) getModel()).eAdapters().add(this);
}
}
/**
* Upon deactivation, detach from the model element as a notification change
* listener.
*/
public void deactivate() {
if (isActive()) {
super.deactivate();
((ModelElement) getModel()).eAdapters().remove(this);
}
}
当模型中的属性发生变化时,会向所有的侦听器发出消息:
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setName(String newName) {
String oldName = name;
name = newName;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, ModelPackage.ARC_MODEL__NAME, oldName, name));
}
对于所有在该模型上注册的侦听器(EditPart)都会接收到属性变化的消息,根据消息做出相应的反应:
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.common.notify.Adapter#notifyChanged(org.eclipse.emf.common.notify.Notification)
*/
public void notifyChanged(Notification notification) {
int featureID = notification.getFeatureID(ModelPackage.class);
if (ModelPackage.NODE_MODEL__HEIGHT == featureID
|| ModelPackage.NODE_MODEL__WIDTH == featureID
|| ModelPackage.NODE_MODEL__X == featureID
|| ModelPackage.NODE_MODEL__Y == featureID) {
refreshVisuals();
} else if (ModelPackage.NODE_MODEL__INPUT_ARCS == featureID) {
refreshTargetConnections();
} else if (ModelPackage.NODE_MODEL__OUTPUT_ARCS == featureID) {
refreshSourceConnections();
}
}
(注意:上述示例代码中,模型部分代码是由EMF自动生成,因此使用了Notifier-Adapter侦听机制)
posted on 2005-11-24 19:57
genesis 阅读(2343)
评论(1) 编辑 收藏 所属分类:
GEF Related