这一篇博客在上一篇的基础上,实现展开/折叠功能。期待的最终效果是,双击某一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(); }
九、此时再运行,则不会出现上述问题。
最终代码在这里