draw2d详述(LightweightSystem)
作为gef的展现层draw2d以其轻量灵活著称,在了解gef的同事,如果不花足够多的时间了解draw2d,就相当你有一半是无知的。
?
?
1.LightweightSystem与GraphicalViewerImpl:
? ?它为SWT与draw2d建立联系,使得Figure能够很好的被Canvas管理。
? ?要达到这个目的,必须做三件事:1.创建一个Canvas。2.创建一个LightweightSystem,并且把Canvas对象传递给它。3.创建一个rootFigure并且把它传递给LightweightSystem。这样LightweightSystem就能管理Canvas和rootFigure的关系了。
?
这三件事在GraphicalViewerImpl里面是可以找的到的:
?
?
protected LightweightSystem createLightweightSystem() {return new LightweightSystem();}?创建LightweightSystem
?
?
public Control createControl(Composite composite) {setControl(new Canvas(composite, SWT.NO_BACKGROUND));return getControl();}?
?
protected void hookControl() {super.hookControl();getLightweightSystem().setControl((Canvas) getControl());getControl().addFocusListener(lFocus = new FocusListener() {public void focusGained(FocusEvent e) {handleFocusGained(e);}public void focusLost(FocusEvent e) {handleFocusLost(e);}});}?创建Canvas并把它赋给LightweightSystem
?
?
protected void setRootFigure(IFigure figure) {rootFigure = figure;getLightweightSystem().setContents(rootFigure);}?rootFigure也被赋给LightweightSystem了。
?
?
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));}?另外还传递了一个DomainEventDispatcher给LightweightSystem了。
?
DomainEventDispatcher是一个事件调度器,它继承自SWTEventDispatcher,在DomainEventDispatcher里面,它是把获取到的事件,转发给EditDomain进行处理,这个可以跟前面EditDomain能够获取到事件这一事实穿起来。
?
总结:在GraphicalViewerImpl里面创建一个LightweightSystem,并且让它管理SWT和draw2d相关组件。当GraphicalViewerImpl要刷新是,也是直接调用LightweightSystem的UpdateManager进行刷新。
?
?
?
2.LightweightSystem的内部:
(1)我们知道Figure不是SWT控件,但是却能够监听很多事件,是谁告诉它的呢?是它的SWT父canvas,canvas会监听事件,然后把事件给EventDispatcher,gef里面是DomainEventDispatcher,DomainEventDispatcher会把事件给EditDomain,EditDomain会把事件给当前活动的tool,tool会给editpart进行处理。(整条路通了)
?
?
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);}});}?(2)上面说道的只是一条路,事件的响应和处理。在LightweightSystem里面,所以设计到对Figure的重绘都是在UpdateManager里面进行的。
?
UpdateManager抽象类里面,主要是描绘脏区域,以及对脏区域进行重绘。
?
?
public void addDirtyRegion(IFigure figure, Rectangle rect) {addDirtyRegion(figure, rect.x, rect.y, rect.width, rect.height);}??
public synchronized void performUpdate(Rectangle exposed) {addDirtyRegion(root, exposed);performUpdate();}?
把rootFigure脏的位置,标记为脏。
?
?
public synchronized void performUpdate() {if (isDisposed() || updating)return;updating = true;try {performValidation();updateQueued = false;repairDamage();if (afterUpdate != null) {RunnableChain chain = afterUpdate;afterUpdate = null;chain.run(); // chain may queue additional Runnable.if (afterUpdate != null)queueWork();}} finally {updating = false;}}?刷新界面,repairDamage方法即是重绘的方法,
?
?
protected void repairDamage() {Iterator keys = dirtyRegions.keySet().iterator();Rectangle contribution;IFigure figure;IFigure walker;while (keys.hasNext()) {figure = (IFigure) keys.next();walker = figure.getParent();contribution = (Rectangle) dirtyRegions.get(figure);// A figure can't paint beyond its own boundscontribution.intersect(figure.getBounds());while (!contribution.isEmpty() && walker != null) {walker.translateToParent(contribution);contribution.intersect(walker.getBounds());walker = walker.getParent();}if (damage == null)damage = new Rectangle(contribution);elsedamage.union(contribution);}if (!dirtyRegions.isEmpty()) {Map oldRegions = dirtyRegions;dirtyRegions = new HashMap();firePainting(damage, oldRegions);}if (damage != null && !damage.isEmpty()) {// ystem.out.println(damage);Graphics graphics = getGraphics(damage);if (graphics != null) {root.paint(graphics);releaseGraphics(graphics);}}damage = null;}?没看的很懂,大致意思就那样,重绘脏区域。
?
?
?
?
?
?
?
?
?
?
?