<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    精彩的人生

    好好工作,好好生活

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      147 Posts :: 0 Stories :: 250 Comments :: 0 Trackbacks

    在使用GEF進行開發的時候,對于需要繪制的圖形的節點,往往除了模型對象本身之外,還需要有一個相應的“圖”對象來保存圖中這個節點的位置,以及大小等圖相關,但是與業務模型無關的一個對象。而在一開始希望顯示一個初始模型文件的時候,再對應保存圖信息的文件不存在的情況下,如何能夠很好的顯示這個圖,是一個比較麻煩的問題,涉及到對布局算法的一些分析與實現。這片文章就是介紹,如何使用GEF內的DirectedGraph這個類以及其相應的布局算法類DirectedGraphLayout,來解決這個問題。
    基本思想是:為
    GEFEditPart模型生成一個DirectedGraph,然后使用DirectedGraphLayout來計算布局,最后將布局的結果通過GEF顯示出來。

     

    在參考了GEFflow example之后,對其代碼作了部分重構,寫了這片文章,希望對遇到同樣問題的同志能夠有一定的幫助。

     

    首先引入一個接口:

    public interface GraphBuilder {

           public void contributeNodesToGraph(DirectedGraph graph, Map map);

           public void contributeEdgesToGraph(DirectedGraph graph, Map map);

           public void applyGraphResults(DirectedGraph graph, Map map);

    }

    這個接口中定義了幾個方法,其含義從其方法名中可以猜出:

    contributeNodesToGraph:將當前對象作為節點(Node)添加到DirectedGraph中。

    contributeEdgesToGraph:將當前對象所對應的連線作為邊(Edge)添加到DirectedGraph中。

    applyGraphResults:將圖中生成的布局信息取出,對本對象進行重新布局。

    接口中的graph參數就是保存的圖的信息,map參數維持一個對象到節點/邊的映射,使得每個對象能夠方便的找到其對應的圖中的節點或者邊。這個接口的使用,在后面會有涉及。下面先看看顯示圖的容器是如何構建的。

     

    圖的容器定義為GraphDiagramEditPart,這個EditPart對應于要顯示的有向圖的容器。它實現了GraphBuider接口,這也是我們主要需要關注的接口:

    public class GraphDiagramEditPart extends AbstractGraphicalEditPart implements

                  GraphBuilder.

     

    contributeNodesToGraph方法將自身作為節點添加到圖中,但是因為GraphDiagramEditPart對應的是容器,因此它不需要向圖中添加信息,只是調用其子EditPart,將其添加到圖中。

           public void contributeNodesToGraph(DirectedGraph graph, Map map) {

                  for (int i = 0; i < getChildren().size(); i++) {

                         NodeEditPart activity = (NodeEditPart)getChildren().get(i);

                         activity.contributeNodesToGraph(graph, map);

                  }

           }

     

    contributeEdgesToGraph方法將這個EditPart的所有子EditPart取出,調用其contributeEdgesToGraph方法,通過這個方法,就可以將所有的邊添加到圖中了:

           public void contributeEdgesToGraph(DirectedGraph graph, Map map) {

                  for (int i = 0; i < getChildren().size(); i++) {

                         NodeEditPart child = (NodeEditPart)children.get(i);

                         child.contributeEdgesToGraph(graph, map);

                  }

           }

     

    applyGraphResults方法將所有取出所有的子EditPart,并調用其applyGraphResults,使得圖中所生成的布局信息能夠被應用到顯示上。

           public void applyGraphResults(DirectedGraph graph, Map map) {

                  applyChildrenResults(graph, map);

           }

           protected void applyChildrenResults(DirectedGraph graph, Map map) {

                  for (int i = 0; i < getChildren().size(); i++) {

                         GraphBuilder part = (GraphBuilder) getChildren().get(i);

                         part.applyGraphResults(graph, map);

                  }

           }

     

    下面要介紹的是NodeEditPart,它作圖中所有節點所對應的EditPart的抽象父類,也實現了GraphBuilder接口。每一個要做為節點添加到圖中的EditPart,應該繼承這個類。

    public abstract class NodeEditPart extends AbstractGraphicalEditPart implements

                  GraphBuilder{

     

           public void contributeNodesToGraph(DirectedGraph graph,

                         Map map) {

                  Node n = new Node(this);

                  n.outgoingOffset = 7;

                  n.incomingOffset = 7;

                  n.width = getFigure().getPreferredSize().width;

                  n.height = getFigure().getPreferredSize().height;

                  n.setPadding(new Insets(10,8,10,12));

                  map.put(this, n);

                  graph.nodes.add(n);

           }

     

           public void contributeEdgesToGraph(DirectedGraph graph, Map map) {

                  List outgoing = getSourceConnections();

                  for (int i = 0; i < outgoing.size(); i++) {

                         EdgeEditPart part = (EdgeEditPart)getSourceConnections().get(i);

                         part.contributeEdgesToGraph(graph, map);

                  }

           }

     

           public void applyGraphResults(DirectedGraph graph, Map map) {

                  Node n = (Node)map.get(this);

                  getFigure().setBounds(new Rectangle(n.x, n.y, n.width, n.height));

                  for (int i = 0; i < getSourceConnections().size(); i++) {

                         EdgeEditPart trans = (EdgeEditPart) getSourceConnections().get(i);

                         trans.applyGraphResults(graph, map);

                  }

           }

    }

     

    再就是邊所對應EditPart的抽象類EdgeEditPart。每一個要作為邊添加到圖中的EditPart,需要繼承這個類。在上面NodeEditPart中對其所對應的Figure其實并沒有什么要求,但是對EdgeEditPart所對應的Figure,要求其Figure必須由一個BendpointConnectionRouter,作為其ConnectionRoutersetConnectionRouter(new BendpointConnectionRouter())。這樣圖的邊的路徑信息才能夠被顯示出來。

    public abstract class EdgeEditPart extends AbstractConnectionEditPart implements

                  GraphBuilder {

     

           public void contributeEdgesToGraph(DirectedGraph graph, Map map) {

                  Node source = (Node)map.get(getSource());

                  Node target = (Node)map.get(getTarget());

                  Edge e = new Edge(this, source, target);

                  e.weight = 2;

                  graph.edges.add(e);

                  map.put(this, e);

           }

     

           public void applyGraphResults(DirectedGraph graph, Map map) {

                  Edge e = (Edge)map.get(this);

                  NodeList nodes = e.vNodes;

                  PolylineConnection conn = (PolylineConnection)getConnectionFigure();

                  conn.setTargetDecoration(new PolygonDecoration());

                  if (nodes != null) {

                         List bends = new ArrayList();

                         for (int i = 0; i < nodes.size(); i++) {

                                Node vn = nodes.getNode(i);

                                int x = vn.x;

                                int y = vn.y;

                                if (e.isFeedback) {

                                       bends.add(new AbsoluteBendpoint(x, y + vn.height));

                                       bends.add(new AbsoluteBendpoint(x, y));

     

                                } else {

                                       bends.add(new AbsoluteBendpoint(x, y));

                                       bends.add(new AbsoluteBendpoint(x, y + vn.height));

                                }

                         }

                         conn.setRoutingConstraint(bends);

                  } else {

                         conn.setRoutingConstraint(Collections.EMPTY_LIST);

                  }

           }

    }

     

    最后的就是一個LayoutManager來初始化圖的創建,以及對圖的信息進行解釋了,生成最終布局了。這個GraphLayoutManager作為GraphDiagramEditPart所對應的GraphDiagramLayoutManager,來顯示圖的內容。

    public class GraphLayoutManager extends AbstractLayout {

           private GraphBuilder diagram;

     

           GraphLayoutManager(GraphBuilder diagram) {

                  this.diagram = diagram;

           }

     

           protected Dimension calculatePreferredSize(IFigure container, int wHint,

                         int hHint) {

                  container.validate();

                  List children = container.getChildren();

                  Rectangle result = new Rectangle().setLocation(container

                                .getClientArea().getLocation());

                  for (int i = 0; i < children.size(); i++)

                         result.union(((IFigure) children.get(i)).getBounds());

                  result.resize(container.getInsets().getWidth(), container.getInsets()

                                .getHeight());

                  return result.getSize();

           }

     

           public void layout(IFigure container) {

                  DirectedGraph graph = new DirectedGraph();

                  Map partsToNodes = new HashMap();

                  diagram.contributeNodesToGraph(graph, partsToNodes);

                  diagram.contributeEdgesToGraph(graph, partsToNodes);

                  new DirectedGraphLayout().visit(graph);

                  diagram.applyGraphResults(graph, partsToNodes);

           }

    }

    可以看到在layout方法中,首先生成了一個DirectedGraph,并調用了contributeNodesToGraph以及contributeEdgesToGraph方法,將節點和邊的信息添加到這個生成的DirectedGraphGraph中,然后使用布局算法DirectedGraphLayout().visit(graph)來計算生成圖的信息(這里使用了visitor模式)最后調用applyGraphResults將圖的信息應用到圖形的顯示上。

     

    至此,所有框架的工作做完了,如果要將模型作為一個有向圖顯示的話,只需要將模型的容器對象對應于GraphDiagramEditPart(在EditPartFactory中進行映射),為每一個需要表示為節點的對象,對應到一個繼承于NodeEditPartEditPart,為每一個需要表示為邊的模型對象,對應到一個繼承于EdgeEditPartEditPart。這樣,就能夠將圖的布局算法,應用到GEF框架中了。

     

    這里寫的比較簡單,使用起來也會有一些具體的約束。例如在有向圖中,是不能夠有孤立的節點的。如果使用CompoundDirectedGraph,就不會有這樣的問題,CompoundDirectedGraph可以包括子圖,可以支持更為復雜的圖形。在Flow Example中使用的就是CompoundDirectedGraph。在后面,我或許會將這個框架進行改寫,以使其支持CompoundDirectedGraph來進行布局算法。下面的圖是一個生成的例子,大家可以看一下效果:

    example_1.JPG

    這是從OWL文件中讀取內容之后生成的一個圖的表示。可以看到,OWL的節點通過自動圖的自動布局之后,已經有了較好的視覺效果。如果沒有這樣的布局的話,因為單純的OWL文件中并不會包含節點的圖的信息,圖顯示出來會變得非常的亂,所有的節點都會堆在一起。





    原文地址:http://www.tkk7.com/eclipshine/archive/2005/07/22/8195.aspx

    posted on 2005-12-28 16:53 hopeshared 閱讀(658) 評論(0)  編輯  收藏 所屬分類: EMF&GEF
    主站蜘蛛池模板: 亚洲精品无码你懂的| 黄+色+性+人免费| 日韩国产欧美亚洲v片| 婷婷亚洲综合五月天小说 | 自怕偷自怕亚洲精品| 曰韩亚洲av人人夜夜澡人人爽| 成年美女黄网站色大免费视频| 美女内射无套日韩免费播放 | 亚洲精品人成无码中文毛片| 成人免费看片又大又黄| 免费在线观看h片| 久久久久久毛片免费播放| 在线免费播放一级毛片 | 国产成人精品日本亚洲专区| 免费看大美女大黄大色| 一级女人18毛片免费| 6080午夜一级毛片免费看 | 亚洲日本中文字幕| 亚洲国产三级在线观看| 国产成人精品久久亚洲| 亚洲国产精品日韩| 免费成人黄色大片| 免费h黄肉动漫在线观看| 国产午夜免费福利红片| 日本久久久免费高清| 女人18特级一级毛片免费视频| 99久久99这里只有免费费精品| 在线观看免费视频资源| 91高清免费国产自产拍2021| 99久久综合精品免费| 亚洲精品免费观看| 91精品啪在线观看国产线免费| 免费A级毛片无码A∨中文字幕下载| 午夜精品射精入后重之免费观看| 久久精品免费视频观看| 日韩免费高清大片在线 | 久久亚洲国产成人影院| 亚洲AV无码无限在线观看不卡 | 日韩av无码成人无码免费| 永久免费毛片在线播放| 在线观看免费a∨网站|