上文提到的GEF工作過程中還有一些不太詳細的地方,這里做些補充。
再GEF中UI的操作交互都是通過構建Request,并調用EditPart中的API來完成相應的操作,這些API可以分為四類:
1。??EditPart getTargetEditPart(Request)
???boolean understandsRequest(Request)
再我們進行交互操作時,首先要確定激活的是那個EditPart,經常是一個當前被選中的viewer和通過單擊選擇的EditPart的復合體。這個被選擇的部件通過詢問每個被選擇的EditPart是否處理這個request(通過understandsRequest方法)。那個在鼠標單擊確定的EditPart是通過viewer的幫助和getTargetEditPart方法來找到的。并不是所有的交互都有target。
2。
void showSourceFeedback(Request)
void eraseSourceFeedback(Request)
void showTargetFeedback(Request)
void eraseTargetFeedback(Request)
在我們的交互操作特別是托拽圖形時,就需要EditPart來回顯(Feedback),托拽源被認為是起作用的那個editpart,目的部件被認為是鼠標的目的地。showXXXFeedback可能是在鼠標移到目的地,但未作用于目的part時調用,eraseXXXFeedback則可能是在鼠標作用于目的part后調用的。
3。Command getCommand(Request)
這個方法用于獲得可執行的命令列表,命令可以對模型進行操作,Editpart通過request詢問Editpolicy來獲得相應的command列表。同時command也可以判斷這個交互操作是否時可能的。如果沒有command或者command不能執行,則ui會指出這個操作是不能執行的(鼠標變成禁止操作的樣子)。如果一個editpart返回null作為command則它不會阻止這個交互操作,除非沒有一個command被提供。為了指示某個操作是不能執行的則EditPart需要返回一個不能執行的command。
4。void performRequest(Request)
還有一種API,它讓EditPart去do something,可能是一些并不會立即就改變model的改變,比如打開對話框或者激活直接編輯模式。
??????? EditPart并不直接進行編輯,它將操作委托給EditPolicy,每個EditPolicy專著于一種編輯任務或者一組相關的操作。當上面的API被調用后(除了performRequest方法),EditPart便委托給它的EditPolicy來處理這個request。對于不同的方法,EditPart可能是在第一個能處理request的policy處就停止調用了或者每個policy都有機會執行這個request。GEF提供了幾個默認的policy,不過還是需要實現其中的一些特定方法。
???????? 這里再廢話一點,在注冊相應的EditPolicy時,需要指定Role,這是一個字符串,用來標示這個EditPolicy,相同的Role對應的EditPolicy會被替換,例如子類可以通過Role這個Key來覆蓋其父類所安裝的EditPolicy。EditPolicy(Role)分成兩種類型,一種是圖形的,一種是非圖形的,上文中有提到,這里詳細的描述一下:
Non-Graphical Roles:
1) COMPONENT_ROLE: 一個Component存在于一個parent中,并且可以從parent中刪除。更為一般的,它可以使任何只涉及到這個EditPart,而與View無關的東西。(More generally, it is anything that involves only this EditPart.)
2) CONNECTION_ROLE 這是ConnectionEditParts應該有的一個基本角色。Connections同Components有一點不同,刪除Connections時通常還需要其從其source和target節點中刪除,而不是從其parent中刪除。
3) CONTAINER_ROLE 大部分擁有children的EditParts都應該具有這個角色。一個Container會涉及到adds/orphans以及creates/deletes等操作。
4) NODE_ROLE 如果一個EditParts用戶Connection,則其應該具有這個角色,它可以用來創建,刪除,重新連接一個Connection。
Graphical Roles:
1) PRIMARY_DRAG_ROLE: 用來允許用戶拖動這個EditPart。用戶可以通過點擊這個EditPart然后拖動,或者點擊這個EditPart所創建的一個Handle來進行拖動。
2) LAYOUT_ROLE: Layout角色用來放在一個Container的EditPart上,這個EditPart擁有一個graphical layout。如果這個layout有constraints,則它需要通過計算來得到這個constraints。
3) GRAPHICAL_NODE_ROLE: A node supports connections to terminals. When creating and manipulating connections, EditPolicies with this role might analyze a Request's data to perform "hit testing" on the graphical view and determine the semantics of the connection. 用于支持連接到重點的node,當創建、操作連接時,包含這個Role的Editpolicy會分析request的數據,來在圖形view上做“hit testing”,并且判斷這個connection的語義。
4) CONNECTION_ENDPOINTS_ROLE: 這個Role允許用戶拖動一個ConnectionEditPart的端點。
5) CONNECTION_BENDPOINTS_ROLE: 這個Role允許用戶能夠在一個Connection中間拖動和創建bendpoints。
6) SELECTION_FEEDBACK_ROLE: 這個角色只是用來顯示feedback。當鼠標進入或者在一個EditPart上暫停時,Selection Tool會發送兩個類型的request給EditPart。安裝了這個角色的EditPart能夠在此時接受這些請求來改變view的樣子,或者彈出tip,label等。
7) TREE_CONTAINER_ROLE: SWT Tree的Layout Role。 本地SWT Tree的Layout Role的等價物。這個EditPolicy應該在樹上顯示反饋并計算索引,就像在file explorer里拖拽一樣。
over。