1   /****************************************************************************
2    **
3    ** This file is part of yFiles-2.5.0.1. 
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-2007 by yWorks GmbH, Vor dem Kreuzberg 28, 
11   ** 72070 Tuebingen, Germany. All rights reserved.
12   **
13   ***************************************************************************/
14  package demo.view.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.BufferedLayouter;
21  import y.layout.GraphLayout;
22  import y.layout.Layouter;
23  import y.layout.hierarchic.IncrementalHierarchicLayouter;
24  import y.layout.hierarchic.incremental.IncrementalHintsFactory;
25  import y.layout.hierarchic.incremental.NodeLayoutDescriptor;
26  import y.layout.hierarchic.incremental.SimplexNodePlacer;
27  import y.util.Maps;
28  import y.view.Arrow;
29  import y.view.EdgeRealizer;
30  import y.view.Graph2D;
31  import y.view.LayoutMorpher;
32  
33  import javax.swing.AbstractAction;
34  import javax.swing.JToolBar;
35  import java.awt.Cursor;
36  import java.awt.event.ActionEvent;
37  
38  /**
39   * This simple demo shows how to use the new {@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  public class SimpleIncrementalHierarchicLayouterDemo extends DemoBase
55  {
56    private DataMap hintMap;
57  
58    private IncrementalHierarchicLayouter hierarchicLayouter;
59    private IncrementalHintsFactory hintsFactory;
60  
61    public SimpleIncrementalHierarchicLayouterDemo()
62    {
63      final Graph2D graph = view.getGraph2D();
64      EdgeRealizer defaultER = graph.getDefaultEdgeRealizer();
65      defaultER.setArrow(Arrow.STANDARD);
66  
67      // create a map to store the hints for the incremental layout mechanism
68      hintMap = Maps.createHashedDataMap();
69      graph.addDataProvider(IncrementalHierarchicLayouter.INCREMENTAL_HINTS_DPKEY, hintMap);
70  
71      // create the layouter
72      hierarchicLayouter = new IncrementalHierarchicLayouter();
73  
74      // set some defaults
75      hierarchicLayouter.getEdgeLayoutDescriptor().setMinimumFirstSegmentLength(15);
76      hierarchicLayouter.getEdgeLayoutDescriptor().setMinimumLastSegmentLength(20);
77      hierarchicLayouter.getEdgeLayoutDescriptor().setOrthogonallyRouted(false);
78      hierarchicLayouter.getEdgeLayoutDescriptor().setMinimumDistance(10.0d);
79  
80      hierarchicLayouter.getNodeLayoutDescriptor().setLayerAlignment(0.5d);
81      hierarchicLayouter.setMinimumLayerDistance(30.0d);
82      hierarchicLayouter.getNodeLayoutDescriptor().setNodeLabelMode(NodeLayoutDescriptor.NODE_LABEL_MODE_CONSIDER_FOR_DRAWING);
83  
84      hierarchicLayouter.setConsiderNodeLabelsEnabled(true);
85  
86      ((SimplexNodePlacer) hierarchicLayouter.getNodePlacer()).setBaryCenterModeEnabled(true);
87  
88      // get a reference to a hints factory
89      hintsFactory = hierarchicLayouter.createIncrementalHintsFactory();
90  
91      // disable the component layouter (optional)
92      hierarchicLayouter.setComponentLayouterEnabled(false);
93    }
94  
95    class LayoutFromSketchAction extends AbstractAction
96    {
97      LayoutFromSketchAction()
98      {
99        super("Layout From Sketch");
100     }
101 
102     public void actionPerformed(ActionEvent ev)
103     {
104       calcIncrementalLayout(new NodeList().nodes());
105     }
106   }
107 
108   class LayoutIncrementallyAction extends AbstractAction
109   {
110     LayoutIncrementallyAction()
111     {
112       super("Layout Incrementally");
113     }
114 
115     public void actionPerformed(ActionEvent ev)
116     {
117       calcIncrementalLayout(view.getGraph2D().selectedNodes());
118     }
119   }
120 
121   class LayoutAction extends AbstractAction
122   {
123     LayoutAction()
124     {
125       super("Layout");
126     }
127 
128     public void actionPerformed(ActionEvent ev)
129     {
130       calcFreshLayout();
131     }
132   }
133 
134   protected JToolBar createToolBar()
135   {
136     JToolBar tb = super.createToolBar();
137     tb.add(new LayoutAction());
138     tb.add(new LayoutFromSketchAction());
139     tb.add(new LayoutIncrementallyAction());
140     return tb;
141   }
142 
143   public void calcFreshLayout()
144   {
145     hierarchicLayouter.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_FROM_SCRATCH);
146     calcLayout(hierarchicLayouter);
147   }
148 
149   public void calcIncrementalLayout(NodeCursor incrementalNodes)
150   {
151     try
152     {
153       // mark nodes as "new"
154       for (incrementalNodes.toFirst(); incrementalNodes.ok(); incrementalNodes.next())
155       {
156         hintMap.set(incrementalNodes.node(), hintsFactory.createLayerIncrementallyHint(incrementalNodes.node()));
157       }
158       // read the old nodes from the sketch
159       hierarchicLayouter.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_INCREMENTAL);
160       // calculate the layout incrementally
161       calcLayout(hierarchicLayouter);
162     }
163     finally
164     {
165       // reset the marks
166       for (incrementalNodes.toFirst(); incrementalNodes.ok(); incrementalNodes.next())
167       {
168         hintMap.set(incrementalNodes.node(), null);
169       }
170     }
171   }
172 
173   protected void calcLayout(Layouter layouter)
174   {
175     Graph2D graph = view.getGraph2D();
176     if (!graph.isEmpty())
177     {
178       Cursor oldCursor = view.getCanvasComponent().getCursor();
179       try
180       {
181         GraphLayout result = new BufferedLayouter(layouter).calcLayout(view.getGraph2D());
182         LayoutMorpher morpher = new LayoutMorpher(view, result);
183         morpher.setSmoothViewTransform(true);
184         morpher.setPreferredDuration(300);
185         morpher.execute();
186       }
187       finally
188       {
189         view.getCanvasComponent().setCursor(oldCursor);
190       }
191     }
192     view.fitContent();
193     view.updateView();
194   }
195 
196   /**
197    * Launches this demo.
198    */
199   public static void main(String args[])
200   {
201     initLnF();
202     SimpleIncrementalHierarchicLayouterDemo demo = new SimpleIncrementalHierarchicLayouterDemo();
203     demo.start("Simple IncrementalHierarchicLayouter Demo");
204   }
205 }
206