xdingding |
|
|||
日歷
統(tǒng)計
導(dǎo)航常用鏈接留言簿(11)我參與的團(tuán)隊隨筆分類隨筆檔案最新隨筆
搜索積分與排名
最新評論
閱讀排行榜評論排行榜 |
郁悶!同志們沒有留言,不知是寫的太差,何處需要改進(jìn),還是大家覺得對自己沒有用處.... GEF源碼分析(四) GEF 消息轉(zhuǎn)義 ___ Tool的作用 接著上一節(jié): 我們先解決如下問題: 在界面操作過程中,我們希望面對的是邊框調(diào)整事件,圖形移動事件,或者是編輯文本事件,而不是原始的鼠標(biāo)和鍵盤事件?
術(shù)語定義: 系統(tǒng)UI事件: 一般由某些計算機人機交互硬件發(fā)出信號,并且經(jīng)操作系統(tǒng)理解后產(chǎn)生的事件,例如:原始的鼠標(biāo)的移動、點擊和鍵盤的敲擊事件等。 UI業(yè)務(wù)語義事件: 由系統(tǒng)UI事件和其它UI業(yè)務(wù)語義事件觸發(fā),由UI業(yè)務(wù)代碼理解后產(chǎn)生的事件(操作系統(tǒng)不可理解,同時無任何領(lǐng)域的業(yè)務(wù)語義),如2D圖形的尺寸調(diào)整,2D圖形的點擊,2D圖形的移動。 (其實不僅限于事件的轉(zhuǎn)義,包括UI的改變,也需要由系統(tǒng)UI語義轉(zhuǎn)換到UI業(yè)務(wù)語義來使用)
![]() UI業(yè)務(wù)語義事件在Controller控制中的優(yōu)點是易于理解、維護(hù)和擴(kuò)充,具體的主要有以下方面: a.減少系統(tǒng)UI事件判斷邏輯部分代碼的重復(fù)。比如在Controller部分代碼無需分步著大量邏輯重復(fù)的代碼,當(dāng)鼠標(biāo)移動時去判斷究竟是一個2D圖形的尺寸改變,還是一個2D圖形的移動,還是一組2D圖形的移動,還是2D圖形DragAndDrop的動作。 b.Controller部分的代碼語義明確。在Controller內(nèi)部處理代碼和接口中直接面對的是UI業(yè)務(wù)語義,如圖形的移動,圖形的尺寸改變,這樣、代碼易于理解、調(diào)試等。 b.Controller部分代碼無需為系統(tǒng)UI事件保存狀態(tài)。如2D圖形的移動中,如果這些事件直接在Controller中處理,從開始MouseDown,到MouseMove,到MouseUp過程中,在Controller中要集中保留這樣眾多狀態(tài),極易造成Controller代碼具體多頭職責(zé)的癥狀,從而患上嚴(yán)重的精神分裂:)。
于是乎GEF的FrameWork有給出以下的解決方案:
圖A
GEF通過Tools(根interface是Tool),當(dāng)然在視圖上的Menu和Toolbar是通過Action發(fā)出,這個是eclipse的Workbench機制,在此就不討論了。以下是Tool的類繼承樹:
![]() 圖B
從Tool繼承的這些類均處理一個或者一類UI業(yè)務(wù)語義事件,其中需要保留中間狀態(tài)的子類均以XXXTracker形式出現(xiàn)。 首先這些Tool的實現(xiàn)類通過Tool的接口(上圖右邊),接收界面來的事件,然后調(diào)用內(nèi)部handleXXX,這樣通過內(nèi)部函數(shù)getTargetRequest()[createTargetRequest()]和getSourceRequest()[createSourceRequest()],把系統(tǒng)UI事件轉(zhuǎn)換為UI業(yè)務(wù)語義事件叫Request(如圖C)。至此Tool會通過調(diào)用相關(guān)聯(lián)的EditPart的接口將UI業(yè)務(wù)語義事件通知到EditPart中。于是在Controller(EditPart)中僅僅需要理解處理Request對象。
![]() 圖C
下面以ResizeTracker代碼為例: class ResizeTracker protected Request createSourceRequest() { ChangeBoundsRequest request; request = new ChangeBoundsRequest(REQ_RESIZE); request.setResizeDirection(getResizeDirection()); return request; } protected Command getCommand() { List editparts = getOperationSet(); EditPart part; CompoundCommand command = new CompoundCommand(); command.setDebugLabel("Resize Handle Tracker");//$NON-NLS-1$ for (int i = 0; i < editparts.size(); i++) { part = (EditPart)editparts.get(i); command.add(part.getCommand(getSourceRequest())); } return command.unwrap(); } protected void eraseTargetFeedback() { if (!getFlag(FLAG_TARGET_FEEDBACK)) return; if (getTargetEditPart() != null) getTargetEditPart().eraseTargetFeedback(getSourceRequest()); setFlag(FLAG_TARGET_FEEDBACK, false); } protected boolean handleButtonUp(int button) { if (stateTransition(STATE_DRAG_IN_PROGRESS, STATE_TERMINAL)) { eraseSourceFeedback(); eraseTargetFeedback(); performDrag(); } return true; }
最后還有個問題是
我畫了一個簡要的類圖
大家主要以下兩方面 一、創(chuàng)建這些關(guān)鍵事件處理鏈的過程(注意圖上的粗體文字); 二、消息從SWT中Canvas實例傳遞到Tool過程(圖D中注釋標(biāo)簽的順序);
class GraphicalEditor public void createPartControl(Composite parent) { createGraphicalViewer(parent); } protected void createGraphicalViewer(Composite parent) { GraphicalViewer viewer = new ScrollingGraphicalViewer(); viewer.createControl(parent); setGraphicalViewer(viewer); configureGraphicalViewer(); hookGraphicalViewer(); initializeGraphicalViewer(); } protected void setGraphicalViewer(GraphicalViewer viewer) { getEditDomain().addViewer(viewer); this.graphicalViewer = viewer; } class EditDomain public void addViewer(EditPartViewer viewer) { viewer.setEditDomain(this); if (!viewers.contains(viewer)) viewers.add(viewer); } class GraphicalViewerImpl 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)); }
private final LightweightSystem lws = createLightweightSystem();
class ScrollingGraphicalViewer 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)); } class LightweightSystem public void setEventDispatcher(EventDispatcher dispatcher) { this.dispatcher = dispatcher; //在此Shapes例子中是DomainEventDispatcher dispatcher.setRoot(root); dispatcher.setControl(canvas); } 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.addListener(SWT.MouseWheel, handler); …… setEventDispatcher(getEventDispatcher()); }
class EventHandler implements MouseMoveListener, MouseListener, AccessibleControlListener, KeyListener, TraverseListener, FocusListener, AccessibleListener, MouseTrackListener, Listener { … public void keyPressed(KeyEvent e) { //在此Shapes例子中是DomainEventDispatcher getEventDispatcher().dispatchKeyPressed(e); } … public void mouseDoubleClick(MouseEvent e) { getEventDispatcher().dispatchMouseDoubleClicked(e); } … public void mouseMove(MouseEvent e) { getEventDispatcher().dispatchMouseMoved(e); } public void mouseUp(MouseEvent e) { getEventDispatcher().dispatchMouseReleased(e); } … }
這樣、在圖A中Request發(fā)送到EditPart機制做了簡要的探討。 學(xué)習(xí)了Tool產(chǎn)生Request的機制,可以幫助我們調(diào)試GEF,同時如果在大家自己的程序中需要有新的UI交互類型,也可以試著建立自己的Tool類產(chǎn)生新的Request,這樣在自己的EditPart產(chǎn)生對應(yīng)的Command,這樣就可以處理實現(xiàn)新的UI交互類型。
在下一篇我們探討一下有關(guān)圖A中的EditPart如何產(chǎn)生Command,以及執(zhí)行Command問題。
評論:
|
![]() |
|
Copyright © 般若菩提 | Powered by: 博客園 模板提供:滬江博客 |