1   /****************************************************************************
2    **
3    ** This file is part of yFiles-2.9. 
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-2011 by yWorks GmbH, Vor dem Kreuzberg 28, 
11   ** 72070 Tuebingen, Germany. All rights reserved.
12   **
13   ***************************************************************************/
14  
15  package demo.layout.withoutview;
16  
17  import y.geom.YRectangle;
18  import y.geom.YPoint;
19  import y.geom.OrientedRectangle;
20  import y.layout.*;
21  import y.layout.DefaultLayoutGraph;
22  import y.layout.EdgeLabelModel;
23  import y.layout.LayoutGraph;
24  import y.layout.EdgeLabelLayout;
25  import y.layout.FreeEdgeLabelModel;
26  import y.layout.BufferedLayouter;
27  import y.layout.SliderEdgeLabelModel;
28  import y.layout.EdgeLabelLayoutImpl;
29  import y.layout.hierarchic.IncrementalHierarchicLayouter;
30  import y.layout.labeling.GreedyMISLabeling;
31  import y.util.D;
32  import y.base.Edge;
33  import y.base.EdgeMap;
34  import y.base.Node;
35  import y.layout.PortConstraint;
36  import y.layout.PortConstraintKeys;
37  
38  import java.awt.EventQueue;
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   * @see <a href="http://docs.yworks.com/yfiles/doc/developers-guide/layout_advanced_features.html">Section Advanced Layout Concepts</a> in the yFiles for Java Developer's Guide
59   * @see <a href="http://docs.yworks.com/yfiles/doc/developers-guide/labeling.html">Section Automatic Label Placement</a> in the yFiles for Java Developer's Guide
60   */
61  public class LayoutWithoutAView
62  {
63    
64    /**
65     * Launcher
66     */
67    public static void main(String[] args) {
68      EventQueue.invokeLater(new Runnable() {
69        public void run() {
70          LayoutWithoutAView lwv = new LayoutWithoutAView();
71          lwv.doit();
72        }
73      });
74    }
75  
76    /**
77     * Creates a small graph and applies an hierarchic layout to it.
78     * Two different kinds of edge labeling mechanisms will be applied
79     * to the graph.
80     * <p>
81     * The output of the calculated coordinates will be displayed in the
82     * console.
83     */ 
84    public void doit()
85    {
86      DefaultLayoutGraph graph = new DefaultLayoutGraph();
87      
88      //construct graph. assign sizes to nodes
89      Node v1 = graph.createNode();
90      graph.setSize(v1,30,30);
91      Node v2 = graph.createNode();
92      graph.setSize(v2,30,30);
93      Node v3 = graph.createNode();
94      graph.setSize(v3,30,30);
95      
96      Edge e1 = graph.createEdge(v1,v2);
97      Edge e2 = graph.createEdge(v2,v3);
98      Edge e3 = graph.createEdge(v1,v3);
99   
100     //optionally setup some port constraints for HierarchicLayouter
101     EdgeMap spc = graph.createEdgeMap();
102     EdgeMap tpc = graph.createEdgeMap();
103     //e1 shall leave and enter the node on the right side
104     spc.set(e1, PortConstraint.create(PortConstraint.EAST));
105     //additionally set a strong port constraint on the target side. 
106     tpc.set(e1, PortConstraint.create(PortConstraint.EAST, true));
107     //ports with strong port constraints will not be reset by the 
108     //layouter.  So we specify the target port right now to connect 
109     //to the upper-right corner of the node 
110     graph.setTargetPointRel(e1, new YPoint(15, -15));
111     
112     //e2 shall leave and enter the node on the top side
113     spc.set(e2, PortConstraint.create(PortConstraint.NORTH));
114     tpc.set(e2, PortConstraint.create(PortConstraint.NORTH));
115     //e3 uses no port constraints, i.e. layouter will choose best side
116     graph.addDataProvider(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_KEY, spc);
117     graph.addDataProvider(PortConstraintKeys.TARGET_PORT_CONSTRAINT_KEY, tpc);
118     
119     
120     //setup two edge labels for edge e1. The size of the edge labels will be set to
121     //80x20. Usually the size of the labels will be determined by
122     //calculating the bounding box of a piece text that is displayed
123     //with a specific font.
124     EdgeLabelLayoutImpl ell1 = new EdgeLabelLayoutImpl();
125     ell1.setBox(new YRectangle(0,0,80,20));
126     //use a center slider edge model. the label will be placed on top of the
127     //edge owning the label.
128     ell1.setEdgeLabelModel(new SliderEdgeLabelModel(SliderEdgeLabelModel.CENTER_SLIDER));
129     
130     EdgeLabelLayoutImpl ell2 = new EdgeLabelLayoutImpl();
131     ell2.setBox(new YRectangle(0,0,80,20));
132     //use a side slider model. the label will be placed to one of the sides of the
133     //edge owning the label.
134     ell2.setEdgeLabelModel(new SliderEdgeLabelModel(SliderEdgeLabelModel.SIDE_SLIDER));
135     
136     EdgeLabelLayout[] ells = new EdgeLabelLayout[]{ell1, ell2};
137     graph.setLabelLayout(e1, ells);
138     
139     IncrementalHierarchicLayouter layouter = new IncrementalHierarchicLayouter();
140     layouter.setLabelLayouterEnabled(true);
141     layouter.setLabelLayouter(new GreedyMISLabeling());
142     
143     new BufferedLayouter(layouter).doLayout(graph);
144     
145     //display result
146     LayoutPreviewPanel lpp1 = new LayoutPreviewPanel(new CopiedLayoutGraph(graph));
147     lpp1.createFrame("Hierarchical with general edge labeling").setVisible(true);
148     
149     D.bug("\n\nGRAPH LAID OUT USING GENERAL EDGE LABELING");
150     D.bug("v1 center position = " + graph.getCenter(v1));
151     D.bug("v2 center position = " + graph.getCenter(v2));
152     D.bug("v3 center position = " + graph.getCenter(v3));
153     D.bug("e1 path = " + graph.getPath(e1));
154     D.bug("e2 path = " + graph.getPath(e2));
155     D.bug("e3 path = " + graph.getPath(e3));
156     D.bug("ell1 upper left location = " + getEdgeLabelLocation(graph,e1,ell1).getBoundingBox().getLocation());
157     D.bug("ell2 upper left location = " + getEdgeLabelLocation(graph,e1,ell2).getBoundingBox().getLocation());  
158   
159     EdgeLabelModel freeModel = new FreeEdgeLabelModel();
160     ell1.setEdgeLabelModel(freeModel);
161     ell1.setModelParameter(freeModel.getDefaultParameter());
162     ell2.setEdgeLabelModel(freeModel);
163     ell2.setModelParameter(freeModel.getDefaultParameter());
164 
165     layouter = new IncrementalHierarchicLayouter();
166     layouter.setIntegratedEdgeLabelingEnabled(true);
167 
168     new BufferedLayouter(layouter).doLayout(graph);
169     
170     //display result
171     LayoutPreviewPanel lpp2 = new LayoutPreviewPanel(graph);
172     lpp2.createFrame("Hierarchical with internal labeling").setVisible(true);
173 
174     D.bug("\n\nGRAPH LAID OUT USING HIERARCHIC LAYOUTER WITH INTERNAL EDGE LABELING");
175     D.bug("v1 center position = " + graph.getCenter(v1));
176     D.bug("v2 center position = " + graph.getCenter(v2));
177     D.bug("v3 center position = " + graph.getCenter(v3));
178     D.bug("e1 path = " + graph.getPath(e1));
179     D.bug("e2 path = " + graph.getPath(e2));
180     D.bug("e3 path = " + graph.getPath(e3));
181     D.bug("ell1 upper left location = " + getEdgeLabelLocation(graph,e1,ell1).getBoundingBox().getLocation());
182     D.bug("ell2 upper left location = " + getEdgeLabelLocation(graph,e1,ell2).getBoundingBox().getLocation());  
183   }
184   
185   /**
186    * Returns the calculated bounds of the edge label. 
187    */ 
188   OrientedRectangle getEdgeLabelLocation(LayoutGraph graph, Edge e, EdgeLabelLayout ell)
189   {
190     OrientedRectangle orientedRectangle = ell.getLabelModel().getLabelPlacement(
191       ell.getOrientedBox().getSize(),
192       graph.getEdgeLayout(e), 
193       graph.getNodeLayout(e.source()),
194       graph.getNodeLayout(e.target()),
195       ell.getModelParameter());
196     return orientedRectangle;
197   }
198 }
199