GEF 進階,第三部分: Layer

簡介: 在GEF中,畫板是由多個Layer(層)組成的,層也可以看作是對圖形進行的一種分類管理,它使圖形更加明確,層次清晰。程序結構上也更容易理解和維護。層同樣也是可以定製的,本文演示如何實現並插入一個自定義層,並指出了插入自定義層所應該注意的一些問題。

Layer(層)

GEF的圖形是可能分佈在多個層上面的,比如連線是放在Connection Layer(連接層)上的,而普通的圖形(比如Shapes Example裏面的長方形和橢圓)是放置在Primary Layer(主層)上的。不同類型的圖形放置在不同的層上,既易於管理又結構清晰,因此層是一個非要重要的功能。層其實也是一個圖形,和其他圖形一樣都繼承自Figure類,所以我們也可以象添加普通圖形一樣添加層,只不過方式有點不同而已。

我們首先需要知道層是在哪裏創建的,纔好動手修改它們。在GEF中,每一個EditPart Viewer都有一個特殊的EditPart,叫做Root,而層的創建就在其中。因此要添加自定義的層,首先的任務就是擴展Root EditPart,一般來說,我們使用的是ScalableFreeformRootEditPart。

提示: 使用何種Root EditPart也是可以自己控制的,只需要在重載GraphicalEditor的configureGraphicalViewer方法,指定使用我們自己的Root EditPart即可。以下是一段示例代碼,斜黑體部分就是具體的調用:

protected void configureGraphicalViewer() {
	super.configureGraphicalViewer();
	
	GraphicalViewer viewer = getGraphicalViewer();
	viewer.setRootEditPart(new ScalableFreeformRootEditPart());

	// more code
	……………
}

所以,這是我們能夠自定義層的一個前提。

ScalableFreeformRootEditPart的createLayers()方法是創建層的關鍵所在,仔細觀察其實現,不難看出GEF缺省定義瞭如圖1所示的層次結構:


提示: 先添加的層在下,後添加的層在上

我們看到缺省包含了很多層,而且層中還有子層,每個層都有一個關鍵字來標識,我們從下到上做一個簡要的描述:

  • Grid Layer: 網格層,用來顯示一個網格,幫助你定位圖形
  • Primary Layer: 主層,大部分的圖形都放置在這個層
  • Connection Layer: 連接層,連線都放置在這一層
  • Printable Layer: 可打印層,這個層並沒有實際作用,只是用來包含主層和連接層
  • Scaled Feedback Layer: 擴展反饋層,所謂反饋是指操作時顯示的一些提示信息,比如你拖動一個圖形時,會顯示一個虛影,這就是反饋
  • Scalable Layer: 和Printable Layer一樣,只是一個容器層
  • Handle Layer: Handle是指一些可以拖動的小方塊,比如選擇一個圖形時,會顯示八個用於Resize的Handle
  • Feedback Layer: 也是一個反饋層
  • Guide Layer: 幫助層

所有的層我們都可以通過getLayer()方法得到,因此我們有很大的自由去控制這些層的屬性,但是如果我們要添加一個層或者修改一個層的行爲,我們必須實現自己的RootEditPart。

Background Layer (背景層)

出於演示的目的,我們添加一個比較簡單的層,叫做Background Layer,它的用處就是在畫布上顯示一個漸進的背景,我們把這個層添加到Primary Layer之前,避免覆蓋主層上的圖形。

注意,我們添加的這個層只是出於演示目的,實際上添加一個背景色並不用費此周章。我們只是爲了說明如何添加一個自定義的層。

創建BackgroundLayer類

我們首先來創建類,對於層,我們只要繼承Layer類就可以了,而Layer本身繼承自Figure,它沒有添加任何新的方法,如果你擴展過Figure類的話,對此就應該比較熟悉了。由於我們只是畫個漸進背景色,所以只需要重載一下paintFigure方法就可以了。如下

package org.eclipse.gef.examples.shapes.layer;

import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.FreeformLayer;
import org.eclipse.draw2d.Graphics;

public class BackgroundLayer extends FreeformLayer {
	public static final String BACKGROUND_LAYER = "Background Layer";
	
	public BackgroundLayer() {
		setOpaque(true);
	}
	
	@Override
	protected void paintFigure(Graphics graphics) {
		if(isOpaque()) {
			graphics.setForegroundColor(ColorConstants.white);
			graphics.setBackgroundColor(ColorConstants.lightBlue);
			graphics.fillGradient(getBounds(), true);
		}
	}
}

我們最終擴展的是FreeformLayer而不是Layer, 如果直接擴展Layer的話,我們的層會無法自動改變大小。我們推薦從FreeformLayer開始你的工作。

實現MyRootEditPart

由於我們只需要插入一個層,所以我們重載ScalableFreeformRootEditPart中的createPrintableLayers方法就可以了。再次提醒的是要注意插入的位置,先加入的層在下,後加入的在上。


package org.eclipse.gef.examples.shapes.parts;

import org.eclipse.draw2d.ConnectionLayer;
import org.eclipse.draw2d.FreeformLayer;
import org.eclipse.draw2d.FreeformLayeredPane;
import org.eclipse.draw2d.LayeredPane;
import org.eclipse.gef.editparts.ScalableFreeformRootEditPart;
import org.eclipse.gef.examples.shapes.layer.BackgroundLayer;

public class MyRootEditPart extends ScalableFreeformRootEditPart {
	@Override
	protected LayeredPane createPrintableLayers() {
		FreeformLayeredPane layeredPane = new FreeformLayeredPane();
		layeredPane.add(new BackgroundLayer(), BackgroundLayer.BACKGROUND_LAYER);
		layeredPane.add(new FreeformLayer(), PRIMARY_LAYER);
		layeredPane.add(new ConnectionLayer(), CONNECTION_LAYER);
		return layeredPane;
	}
}

讓我們自定義的RootEditPart生效是相當簡單的事,只要修改ShapesEditor. configureGraphicalViewer(),將ScalableFreeformRootEditPart替換爲MyRootEditPart即可。就不列出代碼了。完成之後我們就可以看到畫板有了一個漸進式的背景,如圖2所示:



結束語

GEF中的幾乎一切東西都可以定製,本文介紹的是層的定製,層對於一個複雜圖形應用(比如佈線程序)來說是非常重要的。GEF的RootEditPart是層創建的地方,同時getLayer()方法可以讓我們方便的訪問層對象,而添加一個自定義層也是相當簡單。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章