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.module.LayoutModule;
17  import y.geom.YDimension;
18  import y.layout.ComponentLayouter;
19  import y.option.ConstraintManager;
20  import y.option.OptionHandler;
21  import y.view.hierarchy.GroupLayoutConfigurator;
22  import y.view.hierarchy.HierarchyManager;
23  
24  /**
25   * This module represents an interactive configurator and launcher for
26   * {@link y.layout.ComponentLayouter}.
27   */
28  public class ComponentLayoutModule extends LayoutModule
29  {
30    private static final String COMPONENTLAYOUTER = "COMPONENTLAYOUTER";
31    private static final String STYLE = "STYLE";
32  
33    private static final String STYLE_NONE = "STYLE_NONE";
34    private static final String STYLE_ROWS = "STYLE_ROWS";
35    private static final String STYLE_SINGLE_ROW = "STYLE_SINGLE_ROW";
36    private static final String STYLE_SINGLE_COLUMN = "STYLE_SINGLE_COLUMN";
37    private static final String STYLE_PACKED_COMPACT_RECTANGLE = "STYLE_PACKED_COMPACT_RECTANGLE";
38    private static final String STYLE_PACKED_RECTANGLE = "STYLE_PACKED_RECTANGLE";
39    private static final String STYLE_PACKED_CIRCLE = "STYLE_PACKED_CIRCLE";
40    private static final String STYLE_PACKED_COMPACT_CIRCLE = "STYLE_PACKED_COMPACT_CIRCLE";
41    private static final String FROM_SKETCH = "FROM_SKETCH";
42    private static final String NO_OVERLAP = "NO_OVERLAP";
43    private static final String ASPECT_RATIO = "ASPECT_RATIO";
44    private static final String USE_SCREEN_RATIO = "USE_SCREEN_RATIO";
45    private static final String COMPONENT_SPACING = "COMPONENT_SPACING";
46    private static final String GRID_SPACING = "GRID_SPACING";
47    private static final String GRID_ENABLED = "GRID_ENABLED";
48  
49    // for the option handler
50    private final static String styleEnum[] =
51    {
52            STYLE_NONE,
53            STYLE_ROWS,
54            STYLE_SINGLE_ROW,
55            STYLE_SINGLE_COLUMN,
56            STYLE_PACKED_RECTANGLE,
57            STYLE_PACKED_COMPACT_RECTANGLE,
58            STYLE_PACKED_CIRCLE,
59            STYLE_PACKED_COMPACT_CIRCLE,
60    };
61  
62    private ComponentLayouter layouter;
63  
64    public ComponentLayoutModule()
65    {
66      super (COMPONENTLAYOUTER,
67             "yFiles Layout Team",
68             "Wrapper for ComponentLayouter");
69    }
70  
71    /**
72     * Factory method. Responsible for creating and initializing
73     * the OptionHandler for this module.
74     */
75    protected OptionHandler createOptionHandler()
76    {
77      if (layouter == null){
78        createLayouter();
79      }
80  
81      OptionHandler op = new OptionHandler(getModuleName());
82      ConstraintManager cm = new ConstraintManager(op);
83  
84      op.addEnum(STYLE, styleEnum,
85                 layouter.getStyle() & ComponentLayouter.STYLE_MASK);
86      op.addBool(NO_OVERLAP, (layouter.getStyle() & ComponentLayouter.STYLE_MODIFIER_NO_OVERLAP) != 0);
87      op.addBool(FROM_SKETCH, (layouter.getStyle() & ComponentLayouter.STYLE_MODIFIER_AS_IS) != 0);
88      YDimension size = layouter.getPreferredLayoutSize();
89      op.addBool(USE_SCREEN_RATIO, true);
90      op.addDouble(ASPECT_RATIO, size.width / size.height);
91      cm.setEnabledOnValueEquals(USE_SCREEN_RATIO, Boolean.FALSE, ASPECT_RATIO);
92  
93      op.addDouble(COMPONENT_SPACING, layouter.getComponentSpacing(), 0.0d, 400.0d);
94      op.addBool(GRID_ENABLED, layouter.getGridSpacing() > 0);
95      op.addDouble(GRID_SPACING, layouter.getGridSpacing() > 0 ? layouter.getGridSpacing() : 20.0d);
96      cm.setEnabledOnValueEquals(GRID_ENABLED, Boolean.TRUE, GRID_SPACING);
97  
98      return op;
99    }
100 
101   /**
102    * Module initialization routine. Typically this method is used to 
103    * configure the underlying algorithm with the options found in the
104    * options handler of this module.
105    */
106   protected void init()
107   {
108     createLayouter();
109 
110     OptionHandler op = getOptionHandler();
111 
112     layouter.setComponentArrangementEnabled(true);
113     byte style = (byte) op.getEnum(STYLE);
114     if (op.getBool(NO_OVERLAP)){
115       style |= ComponentLayouter.STYLE_MODIFIER_NO_OVERLAP;
116     }
117     if (op.getBool(FROM_SKETCH)){
118       style |= ComponentLayouter.STYLE_MODIFIER_AS_IS;
119     }
120     layouter.setStyle(style);
121     double w, h;
122     if (op.getBool(USE_SCREEN_RATIO)){
123       w = getGraph2DView().getWidth();
124       h = getGraph2DView().getHeight();
125     } else {
126       w = op.getDouble(ASPECT_RATIO);
127       h = 1.0d/w;
128       w *= 400.d;
129       h *= 400.d;
130     }
131     layouter.setPreferredLayoutSize(w, h);
132     layouter.setComponentSpacing(op.getDouble(COMPONENT_SPACING));
133     if (op.getBool(GRID_ENABLED)){
134       layouter.setGridSpacing(op.getDouble(GRID_SPACING));
135     } else {
136       layouter.setGridSpacing(0);
137     }
138   }
139 
140   /**
141    * Main module execution routine. launches the hierarchic layouter.
142    */
143   protected void mainrun()
144   {
145     try{
146       OptionHandler op = getOptionHandler();
147       if(HierarchyManager.containsGroupNodes(getGraph2D()))
148       {
149         GroupLayoutConfigurator glc = new GroupLayoutConfigurator(getGraph2D());
150         glc.prepareAll();
151         try
152         {
153           launchLayouter(layouter);
154         }
155         finally
156         {
157           if(glc != null)
158           {
159             glc.restoreAll();
160           }
161         }
162       } else {
163         launchLayouter(layouter);
164       }
165     } finally {
166     }
167   }
168 
169   /**
170    * clean up the module, clear temporarily bound dataproviders and
171    * references to the wrapped algorithm.
172    */
173   protected void dispose()
174   {
175     layouter = null;
176   }
177 
178   private void createLayouter()
179   {
180     if(layouter == null)
181     {
182       layouter = new ComponentLayouter();
183     }
184   }
185 }
186