1

次の単純化された EMF モデル構造を想定します。

   Graph
   /   \
Node   Edge

私の GEF エディターでは、 はEditPart次のように編成されています。

GraphEditPart(図=FreeformLayer)抜粋

@Override
protected List<EObject> getModelChildren() {
  List<EObject> childrenList = new ArrayList<EObject>();
  Graph graph = (Graph) getModel();
  childrenList.addAll(graph.getNodes());
  return childrenList;
}

NodeEditPart (図 = 拡張Figure) の抜粋 (どのaがソースまたはターゲットであるかを示す方法も示しますEdgesNode)

@Override
protected List<Edge> getModelSourceConnections() {
  Node node = (Node) getModel();
  Graph graph = node.getGraph();
  String nodeId = node.getId();
  List<Edge> sourceList = new ArrayList<Edge>();
  if (graph != null)
  sourceList.addAll(graph.getOutEdges(nodeId));
  return sourceList;
}

@Override
protected List<Edge> getModelTargetConnections() {
  // Same principle as getModelSourceConnections
}

エディター クラスの抜粋 (重要な場合)

@Override
protected void initializeGraphicalViewer() {
  super.initializeGraphicalViewer();
  GraphicalViewer viewer = getGraphicalViewer();
  viewer.setContents(graph);
  ScalableFreeformRootEditPart root = (ScalableFreeformRootEditPart) viewer.getRootEditPart();
  ConnectionLayer connLayer = (ConnectionLayer) root.getLayer(LayerConstants.CONNECTION_LAYER);
  GraphicalEditPart contentEditPart = (GraphicalEditPart) root.getContents();
  ShortestPathConnectionRouter shortestPathConnectionRouter = new ShortestPathConnectionRouter(contentEditPart.getFigure());
  connLayer.setConnectionRouter(shortestPathConnectionRouter);
}

すべてEditPartの には独自のアダプターがあります (拡張org.eclipse.emf.ecore.util.EContentAdapterまたは実装org.eclipse.emf.common.notify.Adapter)。

これにより、が の子であり、が孤児である、つまり を持たないEditPart構造が得られます。その結果、が追加または削除されるたびに図を更新するのに苦労しました。NodeEditPartGraphEditPartEdgeEditPartparentEdge

でコストのかかる反復を実行してを追加したときに、更新を機能させることができました(これは、新しく作成された を( )に登録する必要があることが通知されます):EdgeGraphAdapterEdgeGraphnewEdge.setGraph(graph)

if (notification.getOldValue() == null && notification.getNewValue() instanceof Edge) {     
  for (Object ep : getChildren()) {
    if (ep instanceof NodeEditPart) { // There are in fact other EditParts as well
      Graph graph = (Graph) getModel();
      NodeEditPart nep = (NodeEditPart) ep;
      Node n = (Node) nep.getModel();
    if (graph.getOutEdges(n.getSId()).contains(notification.getNewValue()) || graph.getInEdges(n.getSId()).contains(notification.getNewValue()))
      nep.refresh();
}

[注:ちなみに、これを行うためのより良い方法を考えられる場合は、お気軽に解決策を教えてください!]

問題

モデル オブジェクトEdgeを削除するときに、エディタから Figureを確実に削除できません。Edgeうまくいくこともあれば、うまくいかないこともあります。

信頼性が低いのは、(a)私の現実のモデルには 3 つの抽象化層があり、(b)異なる EMFAdapterが常に同じ時間順序で変化を認識しない (?) という事実に関係している可能性があると思います。

execute()from はEdgeDeleteCommand単純に を呼び出しますedge.setGraph(null)。これにより、EMF はそれ自体の後でクリーンアップを開始します (つまり、グラフに接続されていないモデル要素がモデルから削除されます)。

それぞれのモデル オブジェクトが孤立Edgeしている場合、それぞれのモデル オブジェクトを削除するときに、どのように s の図を確実に削除できますか?EditPart

4

1 に答える 1

1

ソース モデル オブジェクトとターゲット モデル オブジェクトに、何かが変更されたことを知らせてAdapter、更新を処理させます。EdgeDeleteCommand以下のexecute()方法を想定します。

@Override
public void execute() {
  graph = edge.getGraph();
  source = edge.getSource();
  target = edge.getTarget();

  edge.setGraph(null);
  source.eNotify(new NotificationImpl(Notification.REMOVE, edge, null));
  target.eNotify(new NotificationImpl(Notification.REMOVE, edge, null));
}

edgeコードの最後の 2 行は、オブジェクトが "それらから" 削除されたことをソース モデル要素とターゲット モデル要素に通知します。またはの子ではないため、これは実際には偽の通知メッセージです。ただし、ソースとターゲットに接続されている はこれを登録し、次のように反応できます。edgesourcetargetAdapterNodeEditPart

@Override
public void notifyChanged(Notification notification) {
  switch (notification.getEventType()) {
  case Notification.REMOVE:
    refresh();
    break;

  default:
    break;
  }
}

NodeEditPart.refresh()メソッドが呼び出されgetModelSourceConnections()、「getModelTargetConnections()進行中」になり、それぞれのリストが返さEdgeれ、削除されたものはもう含まれていedge ません。

于 2013-03-12T22:12:46.247 に答える