GMF樹形佈局 2 實現展開/摺疊

這一篇博客在上一篇的基礎上,實現展開/摺疊功能。期待的最終效果是,雙擊某一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();
}

九、此時再運行,則不會出現上述問題。

最終代碼在這裏

雙子座@開源中國

相關文章
相關標籤/搜索