EMF Item Provider機制

Porvider的概念

對於JFace部分的內容已經比較清楚,這裏重點看一下Eclipse中PropertySheet是如何實現的。這涉及到了三個接口,IPropertySourceProvider,IPropertySource,IPropertyDescriptor。而模型對象如果要能夠與PropertySheet進行交互,則必須實現IPropertySource接口。Eclipse能夠自動的通過IPropertySourceProvider(當然也不是自動,用到了Eclipse中的Adapter技術),取得這個實現了IPropertySource的模型對象,並讓PropertySheet對其進行調用。IPropertySource的getPropertyDescriptors()方法取得所有的屬性描述對象,屬性描述對象定義了一個顯示在PropertySheet中的屬性的名稱等一些相關的性質。IPropertySource中的其它方法,提供了對屬性值的顯示與修改的方法。

image001.png

圖摘自(Eclipse Modeling Framework: A Developer's Guide) 

因此可以看到,要實現一個Tree Viewer,則必須有一個實現了ITreeContentProvider 接口的對象爲其提供內容,有一個ILabelProvider接口對象爲其提供顯示的標籤和圖標。對於PropertySheet也是如此,必須有一些實現了IPropertyDescriptors()接口的對象來提供被編輯的屬性描述。EMF.Edit要做的就是這樣的一個工作:它爲EMF模型對象,爲這些不同的Viewer生成Provider,使得EMF模型對象能夠通過那些Viewer進行顯示與編輯。EMF.Edit能夠通過兩種方式來完成這樣的工作,反射機制,以及代碼生成的機制。並且EMF.Edit允許方便的更改所生成的代碼,使得其能夠滿足特定的要求。

EMF.Edit中對EMF模型對象的改變,都是通過一種通用的機制:Command來實現的。EMF.Edit提供了對一些常見的Command的實現,並可支持自定義的Command。從上面的討論可以大概的瞭解到,EMF.Edit提供的是在Eclipse的界面(JFace, PropertySheet, etc)同EMF模型對象之間的一個橋樑,使得能夠通過Eclipse UI來顯示和修改EMF所定義的模型對象。EMF.Edit分爲兩個部分:

1.         org.eclipse.emf.edit: 提供的是底層的與界面無關的部分。

2.         org.eclipse.emf.edit.ui: 提供的是與Eclipse UI相關的實現類。

在EMF.Edit中最重要的概念是Item Provider。EMF.Edit使用一種代理機制,使得大部分與模型對象相關的功能都最終被代理到相關的Item Provider上了。因此Item Provider需要完成下面這4種主要的功能:

1.         實現content 和label provider 的功能。

2.         爲EMF objects提供PropertySource的功能。

3.         作爲Command Factory爲模型對象創建相關的Command。

4.         將EMF模型改變通知到Viewers。

特定的Item Provider通常通過繼承ItemProviderAdapter類來完成全部或者部分的上述功能。Item Provider可以通過代碼生成機制被生成後然後進行適當的修改以滿足要求;另一方面,EMF.Edit也提供了ReflectiveItemProvider,通過EObject的反射機制實現了上述所有的功能。



下面看上述的功能是如何在EMF.Edit中被實現的。

實現content 和label provider 的功能

EMF.Edit提供了通用的AdapterFactoryContentProviderAdapterFactoryLabelProvider實現。也就是說對於一個TableViewer而言,它使用AdapterFactoryContentProviderAdapterFactoryLabelProvider作爲其ContentProviderLabelProvider。AdapterFactoryContentProvider等再將請求轉發到具體的Item Provider上。轉發的過程如下所示,在AdapterFactoryContentProvider中實現的ContentProvider所定義的getChildren()方法:

       public Object[] getChildren(Object object) {

              ITreeItemContentProvider adapter = (ITreeItemContentProvider) adapterFactory

                            .adapt(object, ITreeItemContentProvider.class);

              return adapter.getChildren(object).toArray();

       }

AdapterFactoryContentnProvide通過其adapterFactory,將模型對象object適配到ITreeItemContentProvider上(注意ITreeContentProvider和ITreeItemContentProvider名稱上的區別),然後調用相應的方法。這裏用到的adapter的模式,在Eclipse和EMF中使用的非常廣泛

 image003.png

圖摘自(Eclipse Modeling Framework: A Developer's Guide) 

ITreeContentProvider和ITreeItemContentProvider雖然名稱上有區別,但其實際上功能是類似的,EMF中之所以引入ITreeItemContentProvider,是爲了避免對JFace這樣的UI包的依賴,使得其能夠用到其它的非UI或者非JFace的環境中。這樣的接口有:

l         ITreeItemContentProvider

l         IStructuredItemContentProvider

l         ITableItemLabelProvider

l         IItemLabelProvider

分別對應於JFace中去掉了Item後的接口。

爲EMF objects提供PropertySource的功能

AdapterFactoryContentProvider實際上也實現了IPropertySourceProvider接口,使用如上所述的相同的方式,將模型對象適配到一個IItemPropertySource接口上,對應於IPropertySource。另外的一個EMF類PropertySource通過封裝IItemPropertySource實現了PropertySheet所需要的的IPropertySource接口,並被AdapterFactoryContentProvider所返回。同樣的模式被使用到生成IPropertyDescriptor的EMF實現PropertyDescriptor上。下面的這個圖可以比較清楚的看到這樣的關係。

 image005.png

圖摘自(Eclipse Modeling Framework: A Developer's Guide)

作爲Command Factory爲模型對象創建相關的Command

EMF有其自生的Command框架。在這個框架中,EditingDomain是一個類是於JFace中的Provider的接口,提供對Command的創建。並且,EMF.Edit也有一個實現了這個接口的AdapterFactoryEditingDomain,並將請求轉發到被適配的IEditingDomainItemProvider對象上。

將EMF模型改變通知到Viewers

Item Provider作爲標準的EMF Adapter,當被適配的模型對象發生改變的時候Item Provider的notifyChanged()會被調用。實際上,ItemProvider的notifyChange()只是將請求(經過過濾後)轉給相應的ItemProviderAdapterFacotry,使得其作爲模型事件註冊及響應的中心。如下圖所示:

 image007.png

圖摘自(Eclipse Modeling Framework: A Developer's Guide)

需要注意的是,在這樣情景下,作爲內容顯示部分的Viewer並不是事件監聽者,相應的Provider對象纔是,它監聽事件,並調用Viewer的update()方法以刷新顯示的內容。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章