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.circular.CircularLayouter;
32  import y.layout.partial.PartialLayouter;
33  import y.option.IntOptionItem;
34  import y.option.OptionHandler;
35  
36  import java.awt.EventQueue;
37  import java.util.Locale;
38  
39  /**
40   * This demo shows how to apply the partial layouter to circular layouts. The partial layouter changes the coordinates
41   * for a given set of graph elements (called partial elements). The location or size of the remaining elements (called
42   * fixed elements) is not allowed to be changed. The layout algorithm tries to place the partial elements such that the
43   * resulting drawing (including the fixed elements) has a good quality with respect to common graph drawing aesthetics.
44   * <p/>
45   * Partial node elements can be assigned to so called subgraph components. During the layout process each subgraph
46   * induced by the nodes of a component is first laid out using the specified subgraph layouter. Then, the different
47   * components are placed one-by-one onto the drawing area such that the number of overlaps among graph elements is
48   * small. The user can specify different objectives (placement strategies) for finding 'good' positions for subgraph
49   * components.
50   * <p/>
51   * The demo allows to specify fixed and partial elements. Fixed elements are drawn grey and partial elements orange. To
52   * change the fixed/partial state of elements, select the corresponding elements and click on the "Lock Selected
53   * Elements" or "Unlock Selected Elements" button. The current state of selected elements can be toggled with a
54   * mouse-double-click. To start the partial layouter click on the "Apply Partial Layout" button.
55   *
56   * @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
57   */
58  public class CircularPartialLayoutDemo extends PartialLayoutBase {
59  
60    public CircularPartialLayoutDemo() {
61      this(null);
62    }
63  
64    public CircularPartialLayoutDemo(final String helpFilePath) {
65      super(helpFilePath);
66    }
67  
68    /**
69     * Loads a graph, which contains fix nodes and nodes, which should be integrated into this graph.
70     */
71    protected void loadInitialGraph() {
72      loadGraph("resource/graphCircular.graphml");
73    }
74  
75  
76    protected OptionHandler createOptionHandler() {
77      final OptionHandler layoutOptionHandler = new OptionHandler("Option Table");
78  
79      layoutOptionHandler.addEnum("Subgraph Layout",
80          new Object[]{"Circular Layout", "Unchanged"}, 0);
81      layoutOptionHandler.addEnum("Component Assignment",
82          new Object[]{"Single Nodes", "Connected Graphs"}, 1);
83      layoutOptionHandler.addEnum("Placement Strategy",
84          new Object[]{"Barycenter", "From Sketch"}, 0);
85      layoutOptionHandler.addEnum("Edge Routing Style",
86          new Object[]{"Automatic", "Straight Line", "Organic"}, 0);
87      layoutOptionHandler.addBool("Allow Mirroring", false);
88      layoutOptionHandler.addInt("Minimum Node Distance", 10);
89      layoutOptionHandler.getItem("Minimum Node Distance").setAttribute(
90          IntOptionItem.ATTRIBUTE_MIN_VALUE, new Integer(0));
91  
92      return layoutOptionHandler;
93    }
94  
95    protected Layouter createConfiguredPartialLayouter() {
96      final PartialLayouter partialLayouter = new PartialLayouter();
97  
98      if (optionHandler != null) {
99        final int minNodeDist = optionHandler.getInt("Minimum Node Distance");
100       partialLayouter.setMinimalNodeDistance(minNodeDist);
101       switch (optionHandler.getEnum("Subgraph Layout")) {
102         default:
103         case 0:
104           CircularLayouter layouter = new CircularLayouter();
105           layouter.getSingleCycleLayouter().setMinimalNodeDistance(minNodeDist);
106           partialLayouter.setCoreLayouter(layouter);
107           break;
108         case 1:
109           // is null per default
110       }
111       switch (optionHandler.getEnum("Component Assignment")) {
112         default:
113         case 0:
114           partialLayouter.setComponentAssignmentStrategy(PartialLayouter.COMPONENT_ASSIGNMENT_STRATEGY_SINGLE);
115           break;
116         case 1:
117           partialLayouter.setComponentAssignmentStrategy(PartialLayouter.COMPONENT_ASSIGNMENT_STRATEGY_CONNECTED);
118           break;
119       }
120       switch (optionHandler.getEnum("Placement Strategy")) {
121         default:
122         case 0:
123           partialLayouter.setPositioningStrategy(PartialLayouter.SUBGRAPH_POSITIONING_STRATEGY_BARYCENTER);
124           break;
125         case 1:
126           partialLayouter.setPositioningStrategy(PartialLayouter.SUBGRAPH_POSITIONING_STRATEGY_FROM_SKETCH);
127           break;
128       }
129       switch (optionHandler.getEnum("Edge Routing Style")) {
130         default:
131         case 0:
132           partialLayouter.setEdgeRoutingStrategy(PartialLayouter.EDGE_ROUTING_STRATEGY_AUTOMATIC);
133           break;
134         case 1:
135           partialLayouter.setEdgeRoutingStrategy(PartialLayouter.EDGE_ROUTING_STRATEGY_STRAIGHTLINE);
136           break;
137         case 2:
138           partialLayouter.setEdgeRoutingStrategy(PartialLayouter.EDGE_ROUTING_STRATEGY_ORGANIC);
139           break;
140       }
141       partialLayouter.setMirroringAllowed(optionHandler.getBool("Allow Mirroring"));
142     }
143     return partialLayouter;
144   }
145 
146   /**
147    * Launches this demo.
148    */
149   public static void main(String[] args) {
150     EventQueue.invokeLater(new Runnable() {
151       public void run() {
152         Locale.setDefault(Locale.ENGLISH);
153         initLnF();
154         (new CircularPartialLayoutDemo("resource/circularlayouthelp.html"))
155             .start("Circular Partial Layouter Demo");
156       }
157     });
158   }
159 }
160