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