1   /****************************************************************************
2    * This demo file is part of yFiles for Java 2.14.
3    * Copyright (c) 2000-2017 by yWorks GmbH, Vor dem Kreuzberg 28,
4    * 72070 Tuebingen, Germany. All rights reserved.
5    * 
6    * yFiles demo files exhibit yFiles for Java functionalities. Any redistribution
7    * of demo files in source code or binary form, with or without
8    * modification, is not permitted.
9    * 
10   * Owners of a valid software license for a yFiles for Java version that this
11   * demo is shipped with are allowed to use the demo source code as basis
12   * for their own yFiles for Java powered applications. Use of such programs is
13   * governed by the rights and conditions as set out in the yFiles for Java
14   * license agreement.
15   * 
16   * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
17   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18   * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19   * NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21   * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26   *
27   ***************************************************************************/
28  
29  package demo.layout.withoutview;
30  
31  import y.geom.YRectangle;
32  import y.geom.YPoint;
33  import y.geom.OrientedRectangle;
34  import y.layout.*;
35  import y.layout.DefaultLayoutGraph;
36  import y.layout.EdgeLabelModel;
37  import y.layout.LayoutGraph;
38  import y.layout.EdgeLabelLayout;
39  import y.layout.FreeEdgeLabelModel;
40  import y.layout.BufferedLayouter;
41  import y.layout.SliderEdgeLabelModel;
42  import y.layout.EdgeLabelLayoutImpl;
43  import y.layout.hierarchic.IncrementalHierarchicLayouter;
44  import y.layout.labeling.GreedyMISLabeling;
45  import y.util.D;
46  import y.base.Edge;
47  import y.base.EdgeMap;
48  import y.base.Node;
49  import y.layout.PortConstraint;
50  import y.layout.PortConstraintKeys;
51  
52  import java.awt.EventQueue;
53  
54  /**
55   * This class shows how to use layout and labeling algorithms without using classes 
56   * that are only present in the yFiles Viewer Distribution. Therefore this demo
57   * only outputs the calculated coordinates of the graph layout to the console and 
58   * displays it inside a simple preview panel. 
59   * <br>
60   * In this demo HierarchicLayouter is used to layout a small graph. 
61   * <br>
62   * First the edge labels of the graph will be laid out using a general labeling 
63   * approach that effectively positions the labels after the node and edge positions
64   * have already been fixed.
65   * <br>
66   * Second, a special edge labeling mechanism will be used that is currently only 
67   * available in conjunction with HierarchicLayouter. While laying out the graph the 
68   * edge labels will be considered as well. Therefore the node and edge positions 
69   * can be chosen in such a way that, the labeling does not
70   * introduce overlaps between labels and other entities in the graph.
71   *
72   * @see <a href="http://docs.yworks.com/yfiles/doc/api/index.html#/dguide/layout_advanced_features" target="_blank">Section Advanced Layout Concepts</a> in the yFiles for Java Developer's Guide
73   * @see <a href="http://docs.yworks.com/yfiles/doc/api/index.html#/dguide/labeling" target="_blank">Section Automatic Label Placement</a> in the yFiles for Java Developer's Guide
74   */
75  public class LayoutWithoutAView
76  {
77    
78    /**
79     * Launcher
80     */
81    public static void main(String[] args) {
82      EventQueue.invokeLater(new Runnable() {
83        public void run() {
84          LayoutWithoutAView lwv = new LayoutWithoutAView();
85          lwv.doit();
86        }
87      });
88    }
89  
90    /**
91     * Creates a small graph and applies an hierarchic layout to it.
92     * Two different kinds of edge labeling mechanisms will be applied
93     * to the graph.
94     * <p>
95     * The output of the calculated coordinates will be displayed in the
96     * console.
97     */ 
98    public void doit()
99    {
100     DefaultLayoutGraph graph = new DefaultLayoutGraph();
101     
102     //construct graph. assign sizes to nodes
103     Node v1 = graph.createNode();
104     graph.setSize(v1,30,30);
105     Node v2 = graph.createNode();
106     graph.setSize(v2,30,30);
107     Node v3 = graph.createNode();
108     graph.setSize(v3,30,30);
109     
110     Edge e1 = graph.createEdge(v1,v2);
111     Edge e2 = graph.createEdge(v2,v3);
112     Edge e3 = graph.createEdge(v1,v3);
113  
114     //optionally setup some port constraints for HierarchicLayouter
115     EdgeMap spc = graph.createEdgeMap();
116     EdgeMap tpc = graph.createEdgeMap();
117     //e1 shall leave and enter the node on the right side
118     spc.set(e1, PortConstraint.create(PortConstraint.EAST));
119     //additionally set a strong port constraint on the target side. 
120     tpc.set(e1, PortConstraint.create(PortConstraint.EAST, true));
121     //ports with strong port constraints will not be reset by the 
122     //layouter.  So we specify the target port right now to connect 
123     //to the upper-right corner of the node 
124     graph.setTargetPointRel(e1, new YPoint(15, -15));
125     
126     //e2 shall leave and enter the node on the top side
127     spc.set(e2, PortConstraint.create(PortConstraint.NORTH));
128     tpc.set(e2, PortConstraint.create(PortConstraint.NORTH));
129     //e3 uses no port constraints, i.e. layouter will choose best side
130     graph.addDataProvider(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_KEY, spc);
131     graph.addDataProvider(PortConstraintKeys.TARGET_PORT_CONSTRAINT_KEY, tpc);
132     
133     
134     //setup two edge labels for edge e1. The size of the edge labels will be set to
135     //80x20. Usually the size of the labels will be determined by
136     //calculating the bounding box of a piece text that is displayed
137     //with a specific font.
138     EdgeLabelLayoutImpl ell1 = new EdgeLabelLayoutImpl();
139     ell1.setBox(new YRectangle(0,0,80,20));
140     //use a center slider edge model. the label will be placed on top of the
141     //edge owning the label.
142     ell1.setEdgeLabelModel(new SliderEdgeLabelModel(SliderEdgeLabelModel.CENTER_SLIDER));
143     
144     EdgeLabelLayoutImpl ell2 = new EdgeLabelLayoutImpl();
145     ell2.setBox(new YRectangle(0,0,80,20));
146     //use a side slider model. the label will be placed to one of the sides of the
147     //edge owning the label.
148     ell2.setEdgeLabelModel(new SliderEdgeLabelModel(SliderEdgeLabelModel.SIDE_SLIDER));
149     
150     EdgeLabelLayout[] ells = new EdgeLabelLayout[]{ell1, ell2};
151     graph.setLabelLayout(e1, ells);
152     
153     IncrementalHierarchicLayouter layouter = new IncrementalHierarchicLayouter();
154     layouter.setLabelLayouterEnabled(true);
155     layouter.setLabelLayouter(new GreedyMISLabeling());
156     
157     new BufferedLayouter(layouter).doLayout(graph);
158     
159     //display result
160     LayoutPreviewPanel lpp1 = new LayoutPreviewPanel(new CopiedLayoutGraph(graph));
161     lpp1.createFrame("Hierarchical with general edge labeling").setVisible(true);
162     
163     D.bug("\n\nGRAPH LAID OUT USING GENERAL EDGE LABELING");
164     D.bug("v1 center position = " + graph.getCenter(v1));
165     D.bug("v2 center position = " + graph.getCenter(v2));
166     D.bug("v3 center position = " + graph.getCenter(v3));
167     D.bug("e1 path = " + graph.getPath(e1));
168     D.bug("e2 path = " + graph.getPath(e2));
169     D.bug("e3 path = " + graph.getPath(e3));
170     D.bug("ell1 upper left location = " + getEdgeLabelLocation(graph,e1,ell1).getBoundingBox().getLocation());
171     D.bug("ell2 upper left location = " + getEdgeLabelLocation(graph,e1,ell2).getBoundingBox().getLocation());  
172   
173     EdgeLabelModel freeModel = new FreeEdgeLabelModel();
174     ell1.setEdgeLabelModel(freeModel);
175     ell1.setModelParameter(freeModel.getDefaultParameter());
176     ell2.setEdgeLabelModel(freeModel);
177     ell2.setModelParameter(freeModel.getDefaultParameter());
178 
179     layouter = new IncrementalHierarchicLayouter();
180     layouter.setIntegratedEdgeLabelingEnabled(true);
181 
182     new BufferedLayouter(layouter).doLayout(graph);
183     
184     //display result
185     LayoutPreviewPanel lpp2 = new LayoutPreviewPanel(graph);
186     lpp2.createFrame("Hierarchical with internal labeling").setVisible(true);
187 
188     D.bug("\n\nGRAPH LAID OUT USING HIERARCHIC LAYOUTER WITH INTERNAL EDGE LABELING");
189     D.bug("v1 center position = " + graph.getCenter(v1));
190     D.bug("v2 center position = " + graph.getCenter(v2));
191     D.bug("v3 center position = " + graph.getCenter(v3));
192     D.bug("e1 path = " + graph.getPath(e1));
193     D.bug("e2 path = " + graph.getPath(e2));
194     D.bug("e3 path = " + graph.getPath(e3));
195     D.bug("ell1 upper left location = " + getEdgeLabelLocation(graph,e1,ell1).getBoundingBox().getLocation());
196     D.bug("ell2 upper left location = " + getEdgeLabelLocation(graph,e1,ell2).getBoundingBox().getLocation());  
197   }
198   
199   /**
200    * Returns the calculated bounds of the edge label. 
201    */ 
202   OrientedRectangle getEdgeLabelLocation(LayoutGraph graph, Edge e, EdgeLabelLayout ell)
203   {
204     OrientedRectangle orientedRectangle = ell.getLabelModel().getLabelPlacement(
205       ell.getOrientedBox().getSize(),
206       graph.getEdgeLayout(e), 
207       graph.getNodeLayout(e.source()),
208       graph.getNodeLayout(e.target()),
209       ell.getModelParameter());
210     return orientedRectangle;
211   }
212 }
213