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  package demo.layout.hierarchic;
15  
16  import demo.view.DemoBase;
17  import y.base.DataMap;
18  import y.base.NodeCursor;
19  import y.base.NodeList;
20  import y.layout.Layouter;
21  import y.layout.hierarchic.IncrementalHierarchicLayouter;
22  import y.layout.hierarchic.incremental.IncrementalHintsFactory;
23  import y.layout.hierarchic.incremental.NodeLayoutDescriptor;
24  import y.layout.hierarchic.incremental.SimplexNodePlacer;
25  import y.util.Maps;
26  import y.view.Arrow;
27  import y.view.EdgeRealizer;
28  import y.view.Graph2D;
29  import y.view.hierarchy.HierarchyManager;
30  
31  import javax.swing.AbstractAction;
32  import javax.swing.JToolBar;
33  import java.awt.Cursor;
34  import java.awt.EventQueue;
35  import java.awt.event.ActionEvent;
36  import java.util.Locale;
37  
38  /**
39   * This simple demo shows how to use the {@link IncrementalHierarchicLayouter}
40   * to either calculate a new layout or calculate a new layout given the current
41   * sketch or incrementally layout selected nodes to an already existing graph whose
42   * layout is read from the current sketch.
43   * <br>
44   * <br>
45   * Things to try:
46   * <br>
47   * Create a graph and use the <b>Layout</b> button to lay it out from scratch.
48   * Modify the graph (move nodes and or bends), deselect all elements and
49   * choose <b>Layout From Sketch</b> to recalculate the layout using the given sketch
50   * Add some nodes and connect them to the graph, select the newly added nodes
51   * and choose <b>Layout Incrementally</b> to incrementally "add" the selected
52   * elements optimally into the existing graph.
53   *
54   * @see <a href="http://docs.yworks.com/yfiles/doc/developers-guide/incremental_hierarchical_layouter.html#incremental_hierarchical_layouter">Section Hierarchical Layout Style</a> in the yFiles for Java Developer's Guide
55   */
56  public class SimpleIncrementalHierarchicLayouterDemo extends DemoBase
57  {
58    private DataMap hintMap;
59  
60    private IncrementalHierarchicLayouter hierarchicLayouter;
61    private IncrementalHintsFactory hintsFactory;
62  
63    public SimpleIncrementalHierarchicLayouterDemo()
64    {
65      final Graph2D graph = view.getGraph2D();
66      new HierarchyManager(graph);
67      EdgeRealizer defaultER = graph.getDefaultEdgeRealizer();
68      defaultER.setArrow(Arrow.STANDARD);
69  
70      // create a map to store the hints for the incremental layout mechanism
71      hintMap = Maps.createHashedDataMap();
72      graph.addDataProvider(IncrementalHierarchicLayouter.INCREMENTAL_HINTS_DPKEY, hintMap);
73  
74      // create the layouter
75      hierarchicLayouter = new IncrementalHierarchicLayouter();
76  
77      // set some defaults
78      hierarchicLayouter.getEdgeLayoutDescriptor().setMinimumFirstSegmentLength(15);
79      hierarchicLayouter.getEdgeLayoutDescriptor().setMinimumLastSegmentLength(20);
80      hierarchicLayouter.getEdgeLayoutDescriptor().setOrthogonallyRouted(false);
81      hierarchicLayouter.getEdgeLayoutDescriptor().setMinimumDistance(10.0d);
82  
83      hierarchicLayouter.getNodeLayoutDescriptor().setLayerAlignment(0.5d);
84      hierarchicLayouter.setMinimumLayerDistance(30.0d);
85      hierarchicLayouter.getNodeLayoutDescriptor().setNodeLabelMode(NodeLayoutDescriptor.NODE_LABEL_MODE_CONSIDER_FOR_DRAWING);
86  
87      hierarchicLayouter.setConsiderNodeLabelsEnabled(true);
88  
89      ((SimplexNodePlacer) hierarchicLayouter.getNodePlacer()).setBaryCenterModeEnabled(true);
90  
91      // get a reference to a hints factory
92      hintsFactory = hierarchicLayouter.createIncrementalHintsFactory();
93  
94      // disable the component layouter (optional)
95      hierarchicLayouter.setComponentLayouterEnabled(false);
96  
97      loadGraph("resource/simple.graphml");
98    }
99  
100   class LayoutFromSketchAction extends AbstractAction
101   {
102     LayoutFromSketchAction()
103     {
104       super("Layout From Sketch", SHARED_LAYOUT_ICON);
105     }
106 
107     public void actionPerformed(ActionEvent ev)
108     {
109       calcIncrementalLayout(new NodeList().nodes());
110     }
111   }
112 
113   class LayoutIncrementallyAction extends AbstractAction
114   {
115     LayoutIncrementallyAction()
116     {
117       super("Layout Incrementally", SHARED_LAYOUT_ICON);
118     }
119 
120     public void actionPerformed(ActionEvent ev)
121     {
122       calcIncrementalLayout(view.getGraph2D().selectedNodes());
123     }
124   }
125 
126   class LayoutAction extends AbstractAction
127   {
128     LayoutAction()
129     {
130       super("Layout", SHARED_LAYOUT_ICON);
131     }
132 
133     public void actionPerformed(ActionEvent ev)
134     {
135       calcFreshLayout();
136     }
137   }
138 
139   protected JToolBar createToolBar()
140   {
141     JToolBar tb = super.createToolBar();
142     tb.addSeparator();
143     tb.add(createActionControl(new LayoutAction()));
144     tb.add(createActionControl(new LayoutFromSketchAction()));
145     tb.add(createActionControl(new LayoutIncrementallyAction()));
146     return tb;
147   }
148 
149   public void calcFreshLayout()
150   {
151     hierarchicLayouter.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_FROM_SCRATCH);
152     calcLayout(hierarchicLayouter);
153   }
154 
155   public void calcIncrementalLayout(NodeCursor incrementalNodes)
156   {
157     try
158     {
159       // mark nodes as "new"
160       for (incrementalNodes.toFirst(); incrementalNodes.ok(); incrementalNodes.next())
161       {
162         hintMap.set(incrementalNodes.node(), hintsFactory.createLayerIncrementallyHint(incrementalNodes.node()));
163       }
164       // read the old nodes from the sketch
165       hierarchicLayouter.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_INCREMENTAL);
166       // calculate the layout incrementally
167       calcLayout(hierarchicLayouter);
168     }
169     finally
170     {
171       // reset the marks
172       for (incrementalNodes.toFirst(); incrementalNodes.ok(); incrementalNodes.next())
173       {
174         hintMap.set(incrementalNodes.node(), null);
175       }
176     }
177   }
178 
179   protected void calcLayout(Layouter layouter)
180   {
181     Graph2D graph = view.getGraph2D();
182     if (!graph.isEmpty())
183     {
184       Cursor oldCursor = view.getCanvasComponent().getCursor();
185       try
186       {
187         view.applyLayoutAnimated(layouter);
188       }
189       finally
190       {
191         view.getCanvasComponent().setCursor(oldCursor);
192       }
193     }
194     view.fitContent();
195     view.updateView();
196   }
197 
198   /**
199    * Launches this demo.
200    */
201   public static void main(String[] args) {
202     EventQueue.invokeLater(new Runnable() {
203       public void run() {
204         Locale.setDefault(Locale.ENGLISH);
205         initLnF();
206         (new SimpleIncrementalHierarchicLayouterDemo()).start("Simple IncrementalHierarchicLayouter Demo");
207       }
208     });
209   }
210 }
211