在GMF中,我们创建一个模型的基本流程是:
1.在GMF的Palette面板上的工具进行点击,产生对应的请求
2.当鼠标移到右侧的编辑器上时会根据请求产生对应的CreateElementCommand,当鼠标点击下去时,该命令被执行,
于是工具对应的业务模型,notation模型和对应的editpart全部生成,并在界面上展示出来,但是如何通过其他方式来
产生我们的模型及其UI显示呢。
现在我的程序中,是在Papyrus中,不点击右侧Palette的面板上的泳道工具,就能自动的在左侧的编辑器上创建几个泳道。
功能基本实现:但是还有些瑕疵,就是每次Figure创建出来以后,都显示在编辑器的左上角,当有多个时,就会重叠,不是很友好。
我自己定义了一个创建泳道的命令CreateActivityPartitionModelCommand
参数意义如下: actPartName 泳道的名称
rootEditPart 根EditPart(ActivityDiagramEditPart)
/* * 类名:CreateActivityPartitionModelCommand * 功能:创建泳道的命令 */ public class CreateActivityPartitionModelCommand extends RecordingCommand { private String actPartName; private EditPart rootEditPart; public CreateActivityPartitionModelCommand(String actPartName, EditPart rootEditPart, TransactionalEditingDomain transactionalEditingDomain ) { super(transactionalEditingDomain); this.actPartName = actPartName; this.rootEditPart = rootEditPart; } /* * 填充命令的具体实现内容 , 即将新创建的泳道添加到根模型中去即可(non-Javadoc) * @see org.eclipse.emf.transaction.RecordingCommand#doExecute() */ @Override protected void doExecute() { //UML2 模型----ActivityPartition ActivityPartition newElement = UMLFactory.eINSTANCE.createActivityPartition(); newElement.setName(actPartName); DiagramImpl notationModel = (DiagramImpl) rootEditPart.getModel(); EObject domainElement = newElement; View containerView = notationModel; int index = -1; boolean persisted = true; PreferencesHint preferencesHint = new PreferencesHint("org.eclipse.papyrus.diagram.activity"); createActivityPartition( domainElement, containerView, index, persisted, preferencesHint); } }
/* * 函数名:createActivityPartition * 功能: 创建一个泳道对应的Notation模型 * @param domainElement 对应的业务模型 * @param containerView 它的父亲notation * */ public org.eclipse.gmf.runtime.notation.Node createActivityPartition(EObject domainElement, View containerView, int index, boolean persisted, PreferencesHint preferencesHint) { Shape node = NotationFactory.eINSTANCE.createShape(); node.getStyles().add(NotationFactory.eINSTANCE.createHintedDiagramLinkStyle()); node.setLayoutConstraint(NotationFactory.eINSTANCE.createBounds()); node.setType(UMLVisualIDRegistry.getType(ActivityPartitionEditPart.VISUAL_ID)); ViewUtil.insertChildView(containerView, node, index, persisted); node.setElement(domainElement); // initializeFromPreferences final IPreferenceStore prefStore = (IPreferenceStore)preferencesHint.getPreferenceStore(); PreferenceInitializerForElementHelper.initForegroundFromPrefs(node, prefStore, "ActivityPartition"); PreferenceInitializerForElementHelper.initFontStyleFromPrefs(node, prefStore, "ActivityPartition"); PreferenceInitializerForElementHelper.initBackgroundFromPrefs(node, prefStore, "ActivityPartition"); org.eclipse.gmf.runtime.notation.Node label5118 = createLabel(node, UMLVisualIDRegistry.getType(ActivityPartitionNameEditPart.VISUAL_ID)); createCompartment(node, UMLVisualIDRegistry.getType(ActivityPartitionActivityPartitionContentCompartmentEditPart.VISUAL_ID), false, false, false, false); PreferenceInitializerForElementHelper.initCompartmentsStatusFromPrefs(node, prefStore, "ActivityPartition"); return node; } protected org.eclipse.gmf.runtime.notation.DecorationNode createLabel(View owner, String hint) { DecorationNode rv = NotationFactory.eINSTANCE.createDecorationNode(); rv.setType(hint); ViewUtil.insertChildView(owner, rv, ViewUtil.APPEND, true); return rv; } protected org.eclipse.gmf.runtime.notation.Node createCompartment(View owner, String hint, boolean canCollapse, boolean hasTitle, boolean canSort, boolean canFilter) { //SemanticListCompartment rv = NotationFactory.eINSTANCE.createSemanticListCompartment(); //rv.setShowTitle(showTitle); //rv.setCollapsed(isCollapsed); org.eclipse.gmf.runtime.notation.Node rv; if(canCollapse) { rv = NotationFactory.eINSTANCE.createBasicCompartment(); } else { rv = NotationFactory.eINSTANCE.createDecorationNode(); } rv.setLayoutConstraint(NotationFactory.eINSTANCE.createBounds()); if(hasTitle) { TitleStyle ts = NotationFactory.eINSTANCE.createTitleStyle(); ts.setShowTitle(true); rv.getStyles().add(ts); } if(canSort) { rv.getStyles().add(NotationFactory.eINSTANCE.createSortingStyle()); } if(canFilter) { rv.getStyles().add(NotationFactory.eINSTANCE.createFilteringStyle()); } rv.setType(hint); ViewUtil.insertChildView(owner, rv, ViewUtil.APPEND, true); return rv; }
主要原理:
我们创建ActivityPartition对应的notation模型:Shape,并将我们创建的UML2模型ActivityPartition加入到Shape
中(node.setElement(domainElement))。
当我们将ActivityPartition对应的notation模型:Shape node加入到他的父亲标记模型中去的时候,产生一个NotificationEvent事件,通知其
对应的EditPart,在该EditPart中,有对应的处理函数:handleNotificationEvent(Notification event)。
最终会调用AbstractEditPart中的refreshChildren函数。在该函数中会检查他的孩子模型对应的editpart是否存在或他们的对应关系是否正确。
如果孩子对应的editpart不存在,则创建对应的editpart。refreshChild中editPart = createChild(model);
在函数refreshChild中addChild(editPart, i);会调用editpart的getFigure。创建模型对应的图形并在界面中显示出来。
则一整套东西也自然出来了。
/** * Updates the set of children EditParts so that it is in sync with the * model children. This method is called from {@link #refresh()}, and may * also be called in response to notification from the model. This method * requires linear time to complete. Clients should call this method as few * times as possible. Consider also calling {@link #removeChild(EditPart)} * and {@link #addChild(EditPart, int)} which run in constant time. * <P> * The update is performed by comparing the existing EditParts with the set * of model children returned from {@link #getModelChildren()}. EditParts * whose models no longer exist are {@link #removeChild(EditPart) removed}. * New models have their EditParts {@link #createChild(Object) created}. * <P> * This method should <em>not</em> be overridden. * * @see #getModelChildren() */ protected void refreshChildren() { int i; EditPart editPart; Object model; List children = getChildren(); int size = children.size(); Map modelToEditPart = Collections.EMPTY_MAP; if (size > 0) { modelToEditPart = new HashMap(size); for (i = 0; i < size; i++) { editPart = (EditPart) children.get(i); modelToEditPart.put(editPart.getModel(), editPart); } } List modelObjects = getModelChildren(); for (i = 0; i < modelObjects.size(); i++) { model = modelObjects.get(i); // Do a quick check to see if editPart[i] == model[i] if (i < children.size() && ((EditPart) children.get(i)).getModel() == model) continue; // Look to see if the EditPart is already around but in the // wrong location editPart = (EditPart) modelToEditPart.get(model); if (editPart != null) reorderChild(editPart, i); else { // An EditPart for this model doesn't exist yet. Create and // insert one. editPart = createChild(model); addChild(editPart, i); } } // remove the remaining EditParts size = children.size(); if (i < size) { List trash = new ArrayList(size - i); for (; i < size; i++) trash.add(children.get(i)); for (i = 0; i < trash.size(); i++) { EditPart ep = (EditPart) trash.get(i); removeChild(ep); } } }