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 bounds
			contribution.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);
			else
				damage.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;
	}
 

没看的很懂,大致意思就那样,重绘脏区域。

猜你喜欢

转载自lengbingteng-163-com.iteye.com/blog/1528752