1   /****************************************************************************
2    **
3    ** This file is part of yFiles-2.6. 
4    ** 
5    ** yWorks proprietary/confidential. Use is subject to license terms.
6    **
7    ** Redistribution of this file or of an unauthorized byte-code version
8    ** of this file is strictly forbidden.
9    **
10   ** Copyright (c) 2000-2008 by yWorks GmbH, Vor dem Kreuzberg 28, 
11   ** 72070 Tuebingen, Germany. All rights reserved.
12   **
13   ***************************************************************************/
14  
15  package demo.layout;
16  
17  import javax.swing.JFrame;
18  
19  import y.geom.YRectangle;
20  import y.geom.YPoint;
21  import y.layout.*;
22  import y.layout.DefaultLayoutGraph;
23  import y.layout.EdgeLabelModel;
24  import y.layout.LabelLayoutTranslator;
25  import y.layout.LayoutGraph;
26  import y.layout.EdgeLabelLayout;
27  import y.layout.FreeEdgeLabelModel;
28  import y.layout.BufferedLayouter;
29  import y.layout.SliderEdgeLabelModel;
30  import y.layout.EdgeLabelLayoutImpl;
31  import y.layout.hierarchic.HierarchicLayouter;
32  import y.layout.labeling.GreedyMISLabeling;
33  import y.util.D;
34  import y.base.Edge;
35  import y.base.EdgeMap;
36  import y.base.Node;
37  import y.layout.PortConstraint;
38  import y.layout.PortConstraintKeys;
39  
40  /**
41   * This class shows how to use layout and labeling algorithms without using classes 
42   * that are only present in the yFiles Viewer Distribution. Therefore this demo
43   * only outputs the calculated coordinates of the graph layout to the console and 
44   * displays it inside a simple preview panel. 
45   * <br>
46   * In this demo HierarchicLayouter is used to layout a small graph. 
47   * <br>
48   * First the edge labels of the graph will be laid out using a general labeling 
49   * approach that effectively positions the labels after the node and edge positions
50   * have already been fixed.
51   * <br>
52   * Second, a special edge labeling mechanism will be used that is currently only 
53   * available in conjunction with HierarchicLayouter. While laying out the graph the 
54   * edge labels will be considered as well. Therefore the node and edge positions 
55   * can be chosen in such a way that, the labeling does not
56   * introduce overlaps between labels and other entities in the graph.
57   */
58  public class LayoutWithoutAView
59  {
60    
61    /**
62     * Launcher
63     */
64    public static void main(String[] args)
65    {
66      LayoutWithoutAView lwv = new LayoutWithoutAView();
67      lwv.doit();
68    }
69  
70    /**
71     * Creates a small graph and applies an hierarchic layout to it.
72     * Two different kinds of edge labeling mechanisms will be applied
73     * to the graph.
74     * <p>
75     * The output of the calculated coordinates will be displayed in the
76     * console.
77     */ 
78    public void doit()
79    {
80      DefaultLayoutGraph graph = new DefaultLayoutGraph();
81      
82      //construct graph. assign sizes to nodes
83      Node v1 = graph.createNode();
84      graph.setSize(v1,30,30);
85      Node v2 = graph.createNode();
86      graph.setSize(v2,30,30);
87      Node v3 = graph.createNode();
88      graph.setSize(v3,30,30);
89      
90      Edge e1 = graph.createEdge(v1,v2);
91      Edge e2 = graph.createEdge(v2,v3);
92      Edge e3 = graph.createEdge(v1,v3);
93   
94      //optionally setup some port constraints for HierarchicLayouter
95      EdgeMap spc = graph.createEdgeMap();
96      EdgeMap tpc = graph.createEdgeMap();
97      //e1 shall leave and enter the node on the right side
98      spc.set(e1, PortConstraint.create(PortConstraint.EAST));
99      //additionally set a strong port constraint on the target side. 
100     tpc.set(e1, PortConstraint.create(PortConstraint.EAST, true));
101     //ports with strong port constraints will not be reset by the 
102     //layouter.  So we specify the target port right now to connect 
103     //to the upper-right corner of the node 
104     graph.setTargetPointRel(e1, new YPoint(15, -15));
105     
106     //e2 shall leave and enter the node on the top side
107     spc.set(e2, PortConstraint.create(PortConstraint.NORTH));
108     tpc.set(e2, PortConstraint.create(PortConstraint.NORTH));
109     //e3 uses no port constraints, i.e. layouter will choose best side
110     graph.addDataProvider(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_KEY, spc);
111     graph.addDataProvider(PortConstraintKeys.TARGET_PORT_CONSTRAINT_KEY, tpc);
112     
113     
114     //setup two edge labels for edge e1. The size of the edge labels will be set to
115     //80x20. Usually the size of the labels will be determined by
116     //calculaing the bounding box of a piece text that is displayed
117     //with a specific font.
118     EdgeLabelLayoutImpl ell1 = new EdgeLabelLayoutImpl();
119     ell1.setBox(new YRectangle(0,0,80,20));
120     //use a center slider edge model. the label will be placed on top of the
121     //edge owning the label.
122     ell1.setEdgeLabelModel(new SliderEdgeLabelModel(SliderEdgeLabelModel.CENTER_SLIDER));
123     
124     EdgeLabelLayoutImpl ell2 = new EdgeLabelLayoutImpl();
125     ell2.setBox(new YRectangle(0,0,80,20));
126     //use a side slider model. the label will be placed to one of the sides of the
127     //edge owning the label.
128     ell2.setEdgeLabelModel(new SliderEdgeLabelModel(SliderEdgeLabelModel.SIDE_SLIDER));
129     
130     EdgeLabelLayout[] ells = new EdgeLabelLayout[]{ell1, ell2};
131     graph.setLabelLayout(e1, ells);
132     
133     HierarchicLayouter layouter = new HierarchicLayouter();
134     layouter.setLayoutStyle(HierarchicLayouter.MEDIAN_SIMPLEX);
135     layouter.setLabelLayouterEnabled(true);
136     layouter.setLabelLayouter(new GreedyMISLabeling());
137     
138     new BufferedLayouter(layouter).doLayout(graph);
139     
140     //display result
141     LayoutPreviewPanel lpp1 = new LayoutPreviewPanel(new CopiedLayoutGraph(graph));
142     lpp1.createFrame("Hierarchical with general edge labeling").setVisible(true);
143     
144     D.bug("\n\nGRAPH LAID OUT USING GENERAL EDGE LABELING");
145     D.bug("v1 center position = " + graph.getCenter(v1));
146     D.bug("v2 center position = " + graph.getCenter(v2));
147     D.bug("v3 center position = " + graph.getCenter(v3));
148     D.bug("e1 path = " + graph.getPath(e1));
149     D.bug("e2 path = " + graph.getPath(e2));
150     D.bug("e3 path = " + graph.getPath(e3));
151     D.bug("ell1 upper left location = " + getEdgeLabelLocation(graph,e1,ell1));  
152     D.bug("ell2 upper left location = " + getEdgeLabelLocation(graph,e1,ell2));  
153   
154     EdgeLabelModel freeModel = new FreeEdgeLabelModel();
155     ell1.setEdgeLabelModel(freeModel);
156     ell1.setModelParameter(freeModel.getDefaultParameter());
157     ell2.setEdgeLabelModel(freeModel);
158     ell2.setModelParameter(freeModel.getDefaultParameter());
159     layouter.setLabelLayouterEnabled(true);
160     layouter.setLabelLayouter(new LabelLayoutTranslator());
161     
162     new BufferedLayouter(layouter).doLayout(graph);
163     
164     //display result
165     LayoutPreviewPanel lpp2 = new LayoutPreviewPanel(graph);
166     lpp2.createFrame("Hierarchical with internal labeling").setVisible(true);
167 
168     D.bug("\n\nGRAPH LAID OUT USING HIERARCHIC LAYOUTER WITH INTERNAL EDGE LABELING");
169     D.bug("v1 center position = " + graph.getCenter(v1));
170     D.bug("v2 center position = " + graph.getCenter(v2));
171     D.bug("v3 center position = " + graph.getCenter(v3));
172     D.bug("e1 path = " + graph.getPath(e1));
173     D.bug("e2 path = " + graph.getPath(e2));
174     D.bug("e3 path = " + graph.getPath(e3));
175     D.bug("ell1 upper left location = " + getEdgeLabelLocation(graph,e1,ell1));  
176     D.bug("ell2 upper left location = " + getEdgeLabelLocation(graph,e1,ell2));  
177   }
178   
179   /**
180    * Returns the calculated location of the edge label. Note that the labeling
181    * machinery returns the edge labels positions as a parameter
182    * of the model that belongs to the label. This model parameter can be used
183    * to retrieve the actual location of the label as shown in this method.
184    */ 
185   YPoint getEdgeLabelLocation(LayoutGraph graph, Edge e, EdgeLabelLayout ell)
186   {
187     YPoint ellp = ell.getLabelModel().getLabelPlacement(
188       ell.getBox(),
189       graph.getEdgeLayout(e), 
190       graph.getNodeLayout(e.source()),
191       graph.getNodeLayout(e.target()),
192       ell.getModelParameter());
193     return ellp;
194   }
195 }
196