這一篇博客在上一篇的基礎上,實現展開/摺疊功能。期待的最終效果是,雙擊某一Node,其後面的Node與連線都隱藏;再雙擊時顯示回來。而且摺疊以後,保存關閉,下次打開時還處於摺疊狀態,能夠正確展開。 dom
有一個細節應當注意,以下圖: eclipse
好比摺疊了節點1以後再摺疊節點0,以後再展開節點0的時候,節點1應當仍是處於摺疊狀態。 ide
具體步驟以下: 函數
一、爲了實現這個展開/摺疊操做,而且方便之後實現圖標的更換,能夠在節點的模型文件中添加一個布爾型的變量expanded,用於標識展開狀態。能夠在模型文件中修改,而後從新生成Model Code以及Edit Code,具體操做能夠參考這裏的步驟一、2。注意,將expanded的默認值設爲true。 this
二、建立一個Command,用於實現摺疊或者展開。先在diagram工程下的src目錄下新建一個package,名爲org.eclipse.gmf.examples.mindmap.diagram.edit.commands.custom,在其中新建一個class文件,名爲ExpandOrCollapseCommand,繼承自RecordingCommand。 spa
三、ExpandOrCollapseCommand的構造函數以下,獲取 .net
public ExpandOrCollapseCommand( TransactionalEditingDomain transactionalEditingDomain, TopicEditPart topicEditPart) { super(transactionalEditingDomain); this.sourceEdgeList = ((View) topicEditPart.getModel()).getSourceEdges(); this.setLabel("Expand Or Collapse"); this.topicModel = (Topic) ((View) topicEditPart.getModel()).getElement(); this.isExpanded = topicModel.isExpanded(); this.topicEditPart = topicEditPart; }
四、重寫doExecute()方法: code
@Override protected void doExecute() { if (this.sourceEdgeList.size() > 0) { this.topicModel.setExpanded(!this.isExpanded); this.doExpandOrCollapse(this.topicModel, this.sourceEdgeList, !this.isExpanded); } }五、最關鍵的doExpandOrCollapse方法代碼:
/** * 執行展開或者摺疊功能,而且將子節點的元素也要相應地展開或者摺疊 */ private void doExpandOrCollapse(Topic model, List edgeList, boolean visible) { Iterator<ConnectorImpl> iter = edgeList.iterator(); while (iter.hasNext()) { Edge conn = iter.next(); conn.getTarget().setVisible(visible); Topic targetModel = (Topic) conn.getTarget().getElement(); List targetSourceEdgeList = conn.getTarget().getSourceEdges(); if (this.isExpanded) { // 若是將要摺疊,則應將子節點所有隱藏 doExpandOrCollapse(targetModel, targetSourceEdgeList, false); } else if (!this.isExpanded && targetModel.isExpanded()) { // 若是將要展開,則應將子節點中,在摺疊以前處於展開狀態的展開 doExpandOrCollapse(targetModel, targetSourceEdgeList, true); } } }
六、接下來則要使用這個命令。因爲是雙擊,因此先要捕獲對節點的雙擊事件。在TopicEditPart類中重寫超類中的performRequest(Request request)方法: orm
/** * 捕獲各類事件,如雙擊 */ @Override public void performRequest(Request request) { if (request.getType() == (RequestConstants.REQ_OPEN)) { // 雙擊時展開或者隱藏後面的節點 Topic model = (Topic) ((View) this.getModel()).getElement(); TransactionalEditingDomain domain = TransactionUtil .getEditingDomain(this.getModel()); ExpandOrCollapseCommand command = new ExpandOrCollapseCommand( domain, this); domain.getCommandStack().execute(command); } super.performRequest(request); }
七、如今運行,會發現已經能夠展開/摺疊了,可是,存在一個問題:當把某一節點摺疊,保存關閉後,再打開圖,而後再展開這個節點,與它直接相連的節點並不會立刻顯示,須要保存、關閉以後再打開纔會顯示,以下圖: blog
八、解決上面的問題,須要在TopicEditPart中重寫getModelSourceConnections()方法。若是在超類ShapeNodeEditPart中查看原始的getModelSourceConnections()方法,最終找到ViewUtil中的getSourceConnectionsConnectingVisibleViews(View view)方法,會發現其中有一個判斷:
if (edge.isVisible() && isVisible(target)){ sourceConnections.add(edge); }
而咱們是要獲得全部的edge,不論是否可見。咱們雖然沒有手動調用getModelSourceConnections(),可是在內部它是被調用的,因此,在TopicEditPart中重寫getModelSourceConnections()方法以下:
/** * 重寫getModelSourceConnections()方法 */ @Override protected List getModelSourceConnections() { View view = (View) this.getModel(); if (!view.eIsSet(NotationPackage.Literals.VIEW__SOURCE_EDGES)) return Collections.EMPTY_LIST; return view.getSourceEdges(); }
九、此時再運行,則不會出現上述問題。
最終代碼在這裏