1   /****************************************************************************
2    **
3    ** This file is part of yFiles-2.6. 
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-2008 by yWorks GmbH, Vor dem Kreuzberg 28, 
11   ** 72070 Tuebingen, Germany. All rights reserved.
12   **
13   ***************************************************************************/
14  package demo.module;
15  
16  import y.layout.organic.OrganicLayouter;
17  import y.module.LayoutModule;
18  import y.option.OptionHandler;
19  import y.view.Selections;
20  import y.view.hierarchy.GroupLayoutConfigurator;
21  import y.view.hierarchy.HierarchyManager;
22  
23  /**
24   * This module represents an interactive configurator and launcher for
25   * {@link y.layout.organic.OrganicLayouter}.
26   * It is similar to OrganicLayoutModule which is found in 
27   * the yFiles package y.module.
28   * <br>
29   * This demo shows not only how to write your own LayoutModule and 
30   * OptionHandler but 
31   * also how to configure OrganicLayouter by using its API.
32   * <br>
33   * The module provides an option handler that allows to configure
34   * the layouter interactively.
35   * <br>
36   * A module will be started by calling its start method.
37   * See {@link demo.view.layout.organic.OrganicLayouterDemo} on how this module
38   * is being used within an application.
39   * <br>
40   * When executed as a standalone demo this class will display the 
41   * option handler defined to this module.
42   *
43   */
44  public class OrganicLayoutModule extends LayoutModule
45  {
46    private static final String ACTIVATE_DETERMINISTIC_MODE = "ACTIVATE_DETERMINISTIC_MODE";
47    private static final String ACTIVATE_TREE_BEAUTIFIER = "ACTIVATE_TREE_BEAUTIFIER";
48    private static final String MODE = "MODE";
49    private static final String MAXIMAL_DURATION = "MAXIMAL_DURATION";
50    private static final String ITERATION_FACTOR = "ITERATION_FACTOR";
51    private static final String OBEY_NODE_SIZES = "OBEY_NODE_SIZES";
52    private static final String GRAVITY_FACTOR = "GRAVITY_FACTOR";
53    private static final String SPHERE_OF_ACTION = "SPHERE_OF_ACTION";
54    private static final String INITIAL_PLACEMENT = "INITIAL_PLACEMENT";
55    private static final String PREFERRED_EDGE_LENGTH = "PREFERRED_EDGE_LENGTH";
56    private static final String VISUAL = "VISUAL";
57    private static final String ALGORITHM = "ALGORITHM";
58    private static final String ORGANIC = "ORGANIC";
59    private static final String ONLY_SELECTION = "ONLY_SELECTION";
60    private static final String MAINLY_SELECTION = "MAINLY_SELECTION";
61    private static final String ALL = "ALL";
62    private static final String AS_IS = "AS_IS";
63    private static final String RANDOM = "RANDOM";
64    private static final String AT_ORIGIN = "AT_ORIGIN";
65    private static final String EDGE_LENGTH_DEVIATION = "EDGE_LENGTH_DEVIATION";
66    private static final String REPULSION = "REPULSION";
67    private static final String ATTRACTION = "ATTRACTION";
68    
69    private static final String GROUPING      = "GROUPING";
70    private static final String GROUP_LAYOUT_POLICY = "GROUP_LAYOUT_POLICY";
71    private static final String IGNORE_GROUPS = "IGNORE_GROUPS";
72    private static final String LAYOUT_GROUPS = "LAYOUT_GROUPS";
73    private static final String FIX_GROUPS    = "FIX_GROUPS";
74    private static final String GROUP_NODE_COMPACTNESS = "GROUP_NODE_COMPACTNESS";
75  
76    // for the option handler
77    private final static String initialPlacementEnum[] =
78    { 
79      RANDOM, 
80      AT_ORIGIN,
81      AS_IS 
82    };
83  
84    // for the option handler
85    private final static String sphereOfActionEnum[] =
86    {
87      ALL,
88      MAINLY_SELECTION,
89      ONLY_SELECTION
90    };
91  
92    private OrganicLayouter organic;
93    
94    public OrganicLayoutModule()
95    {
96      super (ORGANIC,
97             "yFiles Layout Team",
98             "Wrapper for OrganicLayouter");
99    }
100 
101   /**
102    * Factory method. Responsible for creating and initializing
103    * the OptionHandler for this module.
104    */
105   protected OptionHandler createOptionHandler()
106   {
107     if (organic == null){
108       createOrganic();
109     }
110     
111     OptionHandler op = new OptionHandler(getModuleName());
112 
113     op.useSection(VISUAL);
114     op.addEnum(SPHERE_OF_ACTION,sphereOfActionEnum,
115                organic.getSphereOfAction());
116     op.addEnum(INITIAL_PLACEMENT,initialPlacementEnum,
117                organic.getInitialPlacement());
118     op.addInt(PREFERRED_EDGE_LENGTH, organic.getPreferredEdgeLength(), 0, 500);
119     op.addBool(OBEY_NODE_SIZES,organic.getObeyNodeSize());
120     op.addInt(ATTRACTION, organic.getAttraction(), 0, 2);
121     op.addInt(REPULSION, organic.getRepulsion(), 0, 2);
122     op.addDouble(GRAVITY_FACTOR,organic.getGravityFactor(),-0.2,2,1);
123     op.addBool(ACTIVATE_TREE_BEAUTIFIER,organic.getActivateTreeBeautifier());
124 
125     op.useSection(ALGORITHM);
126     op.addDouble(ITERATION_FACTOR,organic.getIterationFactor());
127     op.addInt(MAXIMAL_DURATION,(int)(organic.getMaximumDuration()/1000));
128     op.addBool(ACTIVATE_DETERMINISTIC_MODE,organic.getActivateDeterministicMode());
129     
130     op.useSection(GROUPING);
131     String[] gEnum = { LAYOUT_GROUPS, FIX_GROUPS, IGNORE_GROUPS };
132     op.addEnum(GROUP_LAYOUT_POLICY, gEnum, 0);
133     op.addDouble(GROUP_NODE_COMPACTNESS, organic.getGroupNodeCompactness(), 0, 1);
134     return op;
135   }
136 
137   /**
138    * Module initialization routine. Typically this method is used to 
139    * configure the underlying algorithm with the options found in the
140    * options handler of this module.
141    */
142   protected void init()
143   {
144     createOrganic();
145     
146     OptionHandler op = getOptionHandler();
147 
148     organic.setPreferredEdgeLength(op.getInt(VISUAL,PREFERRED_EDGE_LENGTH));
149     organic.setMaximumDuration(1000*op.getInt(ALGORITHM,MAXIMAL_DURATION));
150     organic.setInitialPlacement((byte)OptionHandler.getIndex(initialPlacementEnum,
151                                           op.getString(VISUAL,INITIAL_PLACEMENT)));
152     organic.setSphereOfAction((byte)OptionHandler.getIndex(sphereOfActionEnum,
153                                         op.getString(VISUAL,SPHERE_OF_ACTION)));
154     organic.setGravityFactor(op.getDouble(VISUAL,GRAVITY_FACTOR));
155     organic.setObeyNodeSize(op.getBool(VISUAL,OBEY_NODE_SIZES));
156     organic.setIterationFactor(op.getDouble(ALGORITHM,ITERATION_FACTOR));
157     organic.setActivateTreeBeautifier(op.getBool(VISUAL,ACTIVATE_TREE_BEAUTIFIER));
158     organic.setActivateDeterministicMode(op.getBool(ALGORITHM,ACTIVATE_DETERMINISTIC_MODE));
159     organic.setAttraction(op.getInt(VISUAL,ATTRACTION));
160     organic.setRepulsion(2-op.getInt(VISUAL,REPULSION));
161     organic.setGroupNodeCompactness(op.getDouble(GROUPING, GROUP_NODE_COMPACTNESS));
162   }
163   
164   /**
165    * Main module execution routine. launches the hierarchic layouter.
166    */
167   protected void mainrun()
168   {
169     try{
170       getGraph2D().addDataProvider(OrganicLayouter.SPHERE_OF_ACTION_NODES, 
171                   Selections.createSelectionNodeMap(getGraph2D()));
172 
173       OptionHandler op = getOptionHandler();
174       if(HierarchyManager.containsGroupNodes(getGraph2D()))
175       {
176         GroupLayoutConfigurator glc = new GroupLayoutConfigurator(getGraph2D());
177         glc.prepareAll();
178 
179         if (op.get(GROUPING, GROUP_LAYOUT_POLICY).equals(FIX_GROUPS))
180         {
181           organic.setGroupNodePolicy(OrganicLayouter.FIXED_GROUPS_POLICY);
182         } else if (op.get(GROUPING, GROUP_LAYOUT_POLICY).equals(IGNORE_GROUPS)){
183           organic.setGroupNodePolicy(OrganicLayouter.IGNORE_GROUPS_POLICY);
184         } else {
185           organic.setGroupNodePolicy(OrganicLayouter.LAYOUT_GROUPS_POLICY);
186         }
187         
188         try
189         {
190           launchLayouter(organic);
191         }
192         finally
193         {
194           if(glc != null)
195           {
196             glc.restoreAll();
197           }
198         }
199       } else {
200         launchLayouter(organic);
201       }
202     } finally {
203       getGraph2D().removeDataProvider(OrganicLayouter.SPHERE_OF_ACTION_NODES);
204     }
205   }
206   
207   /**
208    * clean up the module, clear temporarily bound dataproviders and
209    * references to the wrapped algorithm.
210    */
211   protected void dispose()
212   {
213     organic = null;
214   }
215   
216   private void createOrganic()
217   {
218     if(organic == null)
219     {
220       organic = new OrganicLayouter();
221     }
222   }
223 }
224 
225