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  package demo.layout.partial;
29  
30  import y.layout.Layouter;
31  import y.layout.orthogonal.OrthogonalGroupLayouter;
32  import y.layout.partial.PartialLayouter;
33  import y.option.OptionHandler;
34  import y.view.Graph2DLayoutExecutor;
35  
36  import javax.swing.AbstractAction;
37  import javax.swing.Action;
38  import javax.swing.JToolBar;
39  import java.awt.EventQueue;
40  import java.awt.event.ActionEvent;
41  import java.util.Locale;
42  
43  /**
44   * This demo shows how to apply the partial layouter to orthogonal layouts. The partial layouter changes the coordinates
45   * for a given set of graph elements (called partial elements). The location or size of the remaining elements (called
46   * fixed elements) is not allowed to be changed. The layout algorithm tries to place the partial elements such that the
47   * resulting drawing (including the fixed elements) has a good quality with respect to common graph drawing aesthetics.
48   * <p/>
49   * Partial node elements can be assigned to so called subgraph components. During the layout process each subgraph
50   * induced by the nodes of a component is first laid out using the specified subgraph layouter. Then, the different
51   * components are placed one-by-one onto the drawing area such that the number of overlaps among graph elements is
52   * small. The user can specify different objectives (placement strategies) for finding 'good' positions for subgraph
53   * components.
54   * <p/>
55   * The demo allows to specify fixed and partial elements. Fixed elements are drawn grey and partial elements orange. To
56   * change the fixed/partial state of elements, select the corresponding elements and click on the "Lock Selected
57   * Elements" or "Unlock Selected Elements" button. The current state of selected elements can be toggled with a
58   * mouse-double-click. To start the partial layouter click on the "Apply Partial Layout" button.
59   *
60   * @see <a href="http://docs.yworks.com/yfiles/doc/api/index.html#/dguide/partial_layout" target="_blank">Section Partial Layout</a> in the yFiles for Java Developer's Guide
61   */
62  public class OrthogonalPartialLayoutDemo extends PartialLayoutBase {
63  
64    public OrthogonalPartialLayoutDemo() {
65      this(null);
66    }
67  
68    public OrthogonalPartialLayoutDemo(final String helpFilePath) {
69      super(helpFilePath);
70    }
71  
72    /**
73     * Loads a graph, which contains fix nodes and nodes, which should be integrated into this graph.
74     */
75    protected void loadInitialGraph() {
76      loadGraph("resource/orthogonal.graphml");
77    }
78  
79    /**
80     * Adds an action for orthogonal layout to the default toolbar.
81     */
82    protected JToolBar createToolBar() {
83      JToolBar toolBar = super.createToolBar();
84  
85      final OrthogonalLayoutAction orthogonalLayoutAction = new OrthogonalLayoutAction("Orthogonal Layout");
86      orthogonalLayoutAction.putValue(Action.SHORT_DESCRIPTION, "Orthogonal Layout");
87      toolBar.add(orthogonalLayoutAction);
88  
89      return toolBar;
90    }
91  
92    protected OptionHandler createOptionHandler() {
93      final OptionHandler layoutOptionHandler = new OptionHandler("Option Table");
94  
95      layoutOptionHandler.addEnum("Subgraph Layout",
96          new Object[]{"Orthogonal Layout", "Unchanged"}, 0);
97      layoutOptionHandler.addInt("Grid Size", 10, 1, 50);
98      layoutOptionHandler.addEnum("Component Assignment",
99          new Object[]{"Single Nodes", "Connected Graphs", "Same Component"}, 0);
100     layoutOptionHandler.addBool("Use Snapping", true);
101     layoutOptionHandler.addBool("Use Sketch", false);
102     layoutOptionHandler.addBool("Resize Fixed Groups", true);
103 
104     return layoutOptionHandler;
105   }
106 
107   protected Layouter createConfiguredPartialLayouter() {
108     final PartialLayouter partialLayouter = new PartialLayouter();
109 
110     if (optionHandler != null) {
111       switch (optionHandler.getEnum("Subgraph Layout")) {
112         default:
113         case 0:
114           partialLayouter.setCoreLayouter(getOrthogonalLayouter());
115           break;
116         case 1:
117           // is null per default
118       }
119       partialLayouter.setPositioningStrategy(
120           optionHandler.getBool(
121               "Use Sketch") ? PartialLayouter.SUBGRAPH_POSITIONING_STRATEGY_FROM_SKETCH : PartialLayouter.SUBGRAPH_POSITIONING_STRATEGY_BARYCENTER);
122 
123       switch (optionHandler.getEnum("Component Assignment")) {
124         default:
125         case 0:
126           partialLayouter.setComponentAssignmentStrategy(PartialLayouter.COMPONENT_ASSIGNMENT_STRATEGY_SINGLE);
127           break;
128         case 1:
129           partialLayouter.setComponentAssignmentStrategy(PartialLayouter.COMPONENT_ASSIGNMENT_STRATEGY_CONNECTED);
130           break;
131         case 2:
132           partialLayouter.setComponentAssignmentStrategy(PartialLayouter.COMPONENT_ASSIGNMENT_STRATEGY_CUSTOMIZED);
133           break;
134       }
135       partialLayouter.setConsiderNodeAlignment(optionHandler.getBool("Use Snapping"));
136       partialLayouter.setFixedGroupResizingEnabled(optionHandler.getBool("Resize Fixed Groups"));
137       partialLayouter.setMinimalNodeDistance(optionHandler.getInt("Grid Size"));
138     }
139     partialLayouter.setEdgeRoutingStrategy(PartialLayouter.EDGE_ROUTING_STRATEGY_ORTHOGONAL);
140     partialLayouter.setLayoutOrientation(PartialLayouter.ORIENTATION_NONE);
141     return partialLayouter;
142   }
143 
144   /**
145    * This method configures and returns the OrthogonalGroupLayouter
146    * @return an instance of OrthogonalGroupLayouter
147    */
148   private OrthogonalGroupLayouter getOrthogonalLayouter() {
149     OrthogonalGroupLayouter layouter = new OrthogonalGroupLayouter();
150     if (optionHandler != null) {
151       layouter.setGrid(optionHandler.getInt("Grid Size"));
152     }
153     return layouter;
154   }
155 
156   /**
157    * Launches the OrthogonalLayouter.
158    */
159   class OrthogonalLayoutAction extends AbstractAction {
160     OrthogonalLayoutAction(String name) {
161       super(name);
162     }
163 
164     public void actionPerformed(ActionEvent e) {
165       Graph2DLayoutExecutor executor = new Graph2DLayoutExecutor();
166       executor.getLayoutMorpher().setEasedExecution(true);
167       executor.getLayoutMorpher().setSmoothViewTransform(true);
168       executor.doLayout(view, getOrthogonalLayouter());
169       view.updateView();
170     }
171   }
172 
173   public static void main(String[] args) {
174     EventQueue.invokeLater(new Runnable() {
175       public void run() {
176         Locale.setDefault(Locale.ENGLISH);
177         initLnF();
178         (new OrthogonalPartialLayoutDemo("resource/orthogonallayouthelp.html"))
179             .start("Orthogonal Partial Layouter Demo");
180       }
181     });
182   }
183 }
184