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.module;
29  
30  import y.module.LayoutModule;
31  import y.module.YModule;
32  
33  import y.geom.YDimension;
34  import y.layout.ComponentLayouter;
35  import y.option.ConstraintManager;
36  import y.option.OptionHandler;
37  import y.option.OptionItem;
38  import y.view.Graph2DView;
39  
40  /**
41   * This module represents an interactive configurator and launcher for
42   * {@link y.layout.ComponentLayouter}.
43   */
44  public class ComponentLayoutModule extends LayoutModule {
45    //// Module 'Component Layout'
46    protected static final String MODULE_COMPONENTLAYOUTER = "COMPONENTLAYOUTER";
47    
48    //// Section 'default' items
49    protected static final String ITEM_STYLE = "STYLE";
50    protected static final String VALUE_STYLE_NONE = "STYLE_NONE";
51    protected static final String VALUE_STYLE_ROWS = "STYLE_ROWS";
52    protected static final String VALUE_STYLE_SINGLE_ROW = "STYLE_SINGLE_ROW";
53    protected static final String VALUE_STYLE_SINGLE_COLUMN = "STYLE_SINGLE_COLUMN";
54    protected static final String VALUE_STYLE_PACKED_RECTANGLE = "STYLE_PACKED_RECTANGLE";
55    protected static final String VALUE_STYLE_PACKED_COMPACT_RECTANGLE = "STYLE_PACKED_COMPACT_RECTANGLE";
56    protected static final String VALUE_STYLE_PACKED_CIRCLE = "STYLE_PACKED_CIRCLE";
57    protected static final String VALUE_STYLE_PACKED_COMPACT_CIRCLE = "STYLE_PACKED_COMPACT_CIRCLE";
58    protected static final String VALUE_STYLE_MULTI_ROWS = "STYLE_MULTI_ROWS";
59    protected static final String VALUE_STYLE_MULTI_ROWS_COMPACT = "STYLE_MULTI_ROWS_COMPACT";
60    protected static final String VALUE_STYLE_MULTI_ROWS_HEIGHT_CONSTRAINED = "STYLE_MULTI_ROWS_HEIGHT_CONSTRAINED";
61    protected static final String VALUE_STYLE_MULTI_ROWS_HEIGHT_CONSTRAINED_COMPACT = "STYLE_MULTI_ROWS_HEIGHT_CONSTRAINED_COMPACT";
62    protected static final String VALUE_STYLE_MULTI_ROWS_WIDTH_CONSTRAINED = "STYLE_MULTI_ROWS_WIDTH_CONSTRAINED";
63    protected static final String VALUE_STYLE_MULTI_ROWS_WIDTH_CONSTRAINED_COMPACT = "STYLE_MULTI_ROWS_WIDTH_CONSTRAINED_COMPACT";
64    protected static final String ITEM_NO_OVERLAP = "NO_OVERLAP";
65    protected static final String ITEM_FROM_SKETCH = "FROM_SKETCH";
66    protected static final String ITEM_USE_SCREEN_RATIO = "USE_SCREEN_RATIO";
67    protected static final String ITEM_ASPECT_RATIO = "ASPECT_RATIO";
68    protected static final String ITEM_COMPONENT_SPACING = "COMPONENT_SPACING";
69    protected static final String ITEM_GRID_ENABLED = "GRID_ENABLED";
70    protected static final String ITEM_GRID_SPACING = "GRID_SPACING";
71  
72    /**
73     * Creates an instance of this module.
74     */
75    public ComponentLayoutModule() {
76      super(MODULE_COMPONENTLAYOUTER);
77    }
78  
79    /**
80     * Creates an OptionHandler and adds the option items used by this module.
81     * @return the created <code>OptionHandler</code> providing module related options
82     */
83    protected OptionHandler createOptionHandler() {
84      final OptionHandler options = new OptionHandler(getModuleName());
85      final ConstraintManager optionConstraints = new ConstraintManager(options);
86      // Defaults provider
87      final ComponentLayouter defaults = new ComponentLayouter();
88  
89      // Populate default section
90      options.addEnum(ITEM_STYLE, new String[]{
91          VALUE_STYLE_NONE,
92          VALUE_STYLE_ROWS,
93          VALUE_STYLE_SINGLE_ROW,
94          VALUE_STYLE_SINGLE_COLUMN,
95          VALUE_STYLE_PACKED_RECTANGLE,
96          VALUE_STYLE_PACKED_COMPACT_RECTANGLE,
97          VALUE_STYLE_PACKED_CIRCLE,
98          VALUE_STYLE_PACKED_COMPACT_CIRCLE,
99          VALUE_STYLE_MULTI_ROWS,
100         VALUE_STYLE_MULTI_ROWS_COMPACT,
101         VALUE_STYLE_MULTI_ROWS_HEIGHT_CONSTRAINED,
102         VALUE_STYLE_MULTI_ROWS_HEIGHT_CONSTRAINED_COMPACT,
103         VALUE_STYLE_MULTI_ROWS_WIDTH_CONSTRAINED,
104         VALUE_STYLE_MULTI_ROWS_WIDTH_CONSTRAINED_COMPACT,
105     }, defaults.getStyle() & ComponentLayouter.STYLE_MASK);
106     options.addBool(ITEM_NO_OVERLAP, (defaults.getStyle() & ComponentLayouter.STYLE_MODIFIER_NO_OVERLAP) != 0);
107     options.addBool(ITEM_FROM_SKETCH, (defaults.getStyle() & ComponentLayouter.STYLE_MODIFIER_AS_IS) != 0);
108     final OptionItem itemUseScreenRatio = options.addBool(ITEM_USE_SCREEN_RATIO, true);
109     final YDimension size = defaults.getPreferredLayoutSize();
110     final OptionItem itemAspectRatio = options.addDouble(ITEM_ASPECT_RATIO, size.width / size.height);
111     options.addDouble(ITEM_COMPONENT_SPACING, defaults.getComponentSpacing(), 0.0d, 400.0d);
112     final OptionItem itemGridEnabled = options.addBool(ITEM_GRID_ENABLED, defaults.getGridSpacing() > 0);
113     final OptionItem itemGridSpacing =
114         options.addDouble(ITEM_GRID_SPACING, defaults.getGridSpacing() > 0 ? defaults.getGridSpacing() : 20.0d);
115     // Enable/disable items depending on specific values
116     optionConstraints.setEnabledOnValueEquals(itemUseScreenRatio, Boolean.FALSE, itemAspectRatio);
117     optionConstraints.setEnabledOnValueEquals(itemGridEnabled, Boolean.TRUE, itemGridSpacing);
118     
119     return options;
120   }
121 
122   /**
123    * Main module execution routine.
124    * Launches the module's underlying algorithm on the module's graph based on user options.
125    */
126   protected void mainrun() {
127     ComponentLayouter component = new ComponentLayouter();
128 
129     final OptionHandler options = getOptionHandler();
130     configure(component, options);
131 
132     launchLayouter(component);
133   }
134   
135   /**
136    * Configures the module's layout algorithm according to the given options.
137    * <p>
138    * Important: This method does also depend on the <code>Graph2DView</code>
139    * of this module in addition to the method's parameters.
140    * </p>
141    * @param component the <code>ComponentLayouter</code> to be configured
142    * @param options the layout options to set
143    */
144   protected void configure(final ComponentLayouter component, final OptionHandler options) {
145     component.setComponentArrangementEnabled(true);
146     
147     byte style = (byte) options.getEnum(ITEM_STYLE);
148     if (options.getBool(ITEM_NO_OVERLAP)) {
149       style |= ComponentLayouter.STYLE_MODIFIER_NO_OVERLAP;
150     }
151     if (options.getBool(ITEM_FROM_SKETCH)) {
152       style |= ComponentLayouter.STYLE_MODIFIER_AS_IS;
153     }
154     component.setStyle(style);
155     
156     double w, h;
157     final Graph2DView view = getGraph2DView();
158     if (options.getBool(ITEM_USE_SCREEN_RATIO) && view != null) {
159       w = view.getWidth();
160       h = view.getHeight();
161     } else {
162       w = options.getDouble(ITEM_ASPECT_RATIO);
163       h = 1.0d/w;
164       w *= 400.d;
165       h *= 400.d;
166     }
167     component.setPreferredLayoutSize(w, h);
168     
169     component.setComponentSpacing(options.getDouble(ITEM_COMPONENT_SPACING));
170     component.setGridSpacing(options.getBool(ITEM_GRID_ENABLED) ? options.getDouble(ITEM_GRID_SPACING) : 0);
171   }
172 }
173