分类:
2009-10-11 18:34:23
----------------------------------------------------------- 转载请注明出处:http://sjj0412.cublog.cn/ -----------------------------------------------------------
本文系本站原创,欢迎转载!
事件处理在图形系统中起着十分重要的作用,gef的图形终归来说是属于swt中的一个控件,所以其事件(消息)来源都是swt系统。
在GEF中,lightweight是gef图形系统的”shell”及”display”,其在swt中的代理是canvas,所以所有的gef的事件来源于这个canvas,下面就看下gef事件处理的流程,首先肯定要监听canvas的事件,这个通过LightweightSystem的addListeners函数注册其内的canvas的各种事件监听器。
Class ScrollingGraphicalViewer
public final Control createControl(Composite parent) {
FigureCanvas canvas = new FigureCanvas(parent, getLightweightSystem());
setControl(canvas);
installRootFigure();
return canvas;
}
Class FigureCanvas
public FigureCanvas(int style, Composite parent, LightweightSystem lws) {
super(parent, checkStyle(style));
getHorizontalBar().setVisible(false);
getVerticalBar().setVisible(false);
this.lws = lws;
lws.setControl(this);
hook();
}
Class LightweightSystem
public void setControl(Canvas c) {
if (canvas == c)
return;
canvas = c;
if ((c.getStyle() & SWT.DOUBLE_BUFFERED) != 0)
getUpdateManager().setGraphicsSource(new NativeGraphicsSource(canvas));
else
getUpdateManager().setGraphicsSource(new BufferedGraphicsSource(canvas));
getEventDispatcher().setControl(c);
addListeners();
//Size the root figure and contents to the current control's size
Rectangle r = new Rectangle(canvas.getClientArea());
r.setLocation(0, 0);
root.setBounds(r);
root.revalidate();
}
//下面这个就是添加canvas的各种事件监听器。
protected void addListeners() {
EventHandler handler = createEventHandler();
canvas.getAccessible().addAccessibleListener(handler);
canvas.getAccessible().addAccessibleControlListener(handler);
canvas.addMouseListener(handler);
canvas.addMouseMoveListener(handler);
canvas.addMouseTrackListener(handler);
canvas.addKeyListener(handler);
canvas.addTraverseListener(handler);
canvas.addFocusListener(handler);
canvas.addDisposeListener(handler);
canvas.addListener(SWT.MouseWheel, handler);
canvas.addControlListener(new ControlAdapter() {
public void controlResized(ControlEvent e) {
LightweightSystem.this.controlResized();
}
});
canvas.addListener(SWT.Paint, new Listener() {
public void handleEvent(Event e) {
LightweightSystem.this.paint(e.gc);
}
});
}
上面的EventHandler 是LightweightSystem 的内部类,故下面的getEventDispatcher 都是LightweightSystem 的函数。
protected class EventHandler
implements MouseMoveListener, MouseListener, AccessibleControlListener, KeyListener,
TraverseListener, FocusListener, AccessibleListener, MouseTrackListener,
Listener, DisposeListener
{
public void handleEvent(Event event) {
// Mouse wheel events
if (event.type == SWT.MouseWheel)
getEventDispatcher().dispatchMouseWheelScrolled(event);
}
/**@see MouseListener#mouseDown(MouseEvent)*/
public void mouseDown(MouseEvent e) {
getEventDispatcher().dispatchMousePressed(e);
}
/**@see MouseListener#mouseUp(MouseEvent)*/
public void mouseUp(MouseEvent e) {
getEventDispatcher().dispatchMouseReleased(e);
}
/**@see DisposeListener#widgetDisposed(DisposeEvent)*/
public void widgetDisposed(DisposeEvent e) {
getUpdateManager().dispose();
}
}
protected EventDispatcher getEventDispatcher() {
if (dispatcher == null)
setEventDispatcher(new SWTEventDispatcher());
return dispatcher;
}
protected EventDispatcher getEventDispatcher() {
if (dispatcher == null)
setEventDispatcher(new SWTEventDispatcher());
return dispatcher;
}
从上面可以看出,swt控件层的事件其实会调用dispatcher的相关处理函数,dispatcher可以看成是消息分发器,只不过是LightweightSystem里的。
那这个dispatcher是怎么赋值的呢?
在gef里是如下过程:
class GraphicalEditor
public void createPartControl(Composite parent) {
createGraphicalViewer(parent);
}
protected void createGraphicalViewer(Composite parent) {
GraphicalViewer viewer = new ScrollingGraphicalViewer();
viewer.createControl(parent);
setGraphicalViewer(viewer);
configureGraphicalViewer();
hookGraphicalViewer();
initializeGraphicalViewer();
}
protected void setGraphicalViewer(GraphicalViewer viewer) {
getEditDomain().addViewer(viewer);
this.graphicalViewer = viewer;
}
class EditDomain
public void addViewer(EditPartViewer viewer) {
viewer.setEditDomain(this);
if (!viewers.contains(viewer))
viewers.add(viewer);
}
//下面 这个函数添加了为LightweightSystem添加了EventDispatcher。
class GraphicalViewerImpl
public void setEditDomain(EditDomain domain) {
super.setEditDomain(domain);
// Set the new event dispatcher, even if the new domain is null. This will dispose
// the old event dispatcher.
getLightweightSystem()
.setEventDispatcher(eventDispatcher = new DomainEventDispatcher(domain, this));
}
class LightweightSystem
public void setEventDispatcher(EventDispatcher dispatcher) {
this.dispatcher = dispatcher; //在此Shapes例子中是DomainEventDispatcher
dispatcher.setRoot(root);
dispatcher.setControl(canvas);
}
下面就看下DomainEventDispatcher的分发流程,我们以键盘消息为例:
Class DomainEventDispatcher
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);
}
}
然后就执行domain的mouseDown;
( 这个domain是在具体GEF编辑器赋值的
Class PracticeEditor extends GraphicalEditorWithPalette
public PracticeEditor() {
setEditDomain(new DefaultEditDomain(this));
}
)
故上面会调用DefaultEditDomain的keydown;
public class DefaultEditDomain
extends EditDomain
{
private IEditorPart editorPart;
public DefaultEditDomain(IEditorPart editorPart) {
setEditorPart(editorPart);
}
public IEditorPart getEditorPart() {
return editorPart;
}
protected void setEditorPart(IEditorPart editorPart) {
this.editorPart = editorPart;
}
所以应该是editdomain的keydown;
Class Editdomain
public void mouseDown(MouseEvent mouseEvent, EditPartViewer viewer) {
Tool tool = getActiveTool();
if (tool != null)
tool.mouseDown(mouseEvent, viewer);
}
而ActiveTool是在创建EditDomain就赋值了的
public EditDomain() {
loadDefaultTool();
}
public void loadDefaultTool() {
setActiveTool(null);
PaletteViewer paletteViewer = getPaletteViewer();
if (paletteRoot != null && paletteViewer != null) {
if (paletteRoot.getDefaultEntry() != null) {
paletteViewer.setActiveTool(paletteRoot.getDefaultEntry());
return;
} else
paletteViewer.setActiveTool(null);
}
setActiveTool(getDefaultTool());
}
public Tool getDefaultTool() {
if (defaultTool == null)
defaultTool = new SelectionTool();
return defaultTool;
}
从上可见ActiveTool默认是SelectionTool。
现在就真正进入gef的事件核心了,对于Tool层的事件处理流程,我将在下面几篇文章里针对不同Tool,分别进行讲解。